二進制部署Kubernetes-v1.14.1集羣

1、部署Kubernetes集羣

1.1 Kubernetes介紹

Kubernetes(K8S)是Google開源的容器集羣管理系統,K8S在Docker容器技術的基礎之上,大大地提升了容器化部署應用簡單高效。而且具有了完整的集羣管理能力,涵蓋項目週期的各個環節。javascript

Docker與Kubernetes聯繫:Docker是一個容器引擎,用於運行容器,Kubernetes是一個容器編排系統,不具有容器引擎功能,相比Docker是一個更高級封裝,而他們在一塊兒堪稱珠聯璧合。css

 

1.2 建立Kubernetes集羣方式

三種部署集羣方式:html

一、Minikube是一個工具,能夠在本地快速運行一個單點的Kubernetes,嘗試Kubernetes或平常開發的用戶使用。不能用於生產環境。java

二、Kubeadm也是一個工具,提供kubeadm init和kubeadm join,用於快速部署Kubernetes集羣。Kubeadm下降部署門檻,但屏蔽了不少細節,遇到問題很難排查。node

三、二進制包,從官方下載發行版的二進制包,手動部署每一個組件,組成Kubernetes集羣。咱們這裏使用二進制包部署Kubernetes集羣,雖然手動部署麻煩點,但學習不少工做原理,更有利於後期維護。linux

 

1.3 集羣部署架構規劃

1.3.1 軟件環境

CentOS:AWSnginx

Docker:18.9.5-cegit

Kubernetes:1.14.1github

Etcd:3.3.12web

Calico:3.6.1

 

1.3.2 服務器角色

角色

IP

組件

k8s-master1

172.31.50.170

kube-apiserver,kube-controller-manager,kube-scheduler,etcd,haproxy,keeplive

k8s-master2

172.31.50.101

kube-apiserver,kube-controller-manager,kube-scheduler,etcd,haproxy,keeplive

k8s-master3

172.31.58.221

kube-apiserver,kube-controller-manager,kube-scheduler,etcd,haproxy,keeplive

k8s-node1

172.31.55.50

kubelet,kube-proxy,docker,calico

k8s-node2

172.31.55.0

kubelet,kube-proxy,docker,calico

 

192.168.10.24

masterHA集羣的vip

 

 

 

 

 

 

 

 

 

 

 

 

1.3.3 拓撲圖

若是不是雲環境,能夠採用主流的軟件負載均衡器,例如LVS、HAProxy、Nginx。這裏使用HAProxy做爲apiserver負載均衡器,架構圖以下:

 

1.3.4 配置防火牆

一、關閉firewall

systemctl stop firewalld.service && systemctl disable firewalld.service

 

二、安裝iptables防火牆

yum install -y iptables-services

#master節點默認該防火牆配置文件

cat /etc/sysconfig/iptables 

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

#node節點清空該配置,後續也不要手動添加規則

echo "" >/etc/sysconfig/iptables

 

三、重啓防火牆

systemctl restart iptables.service && systemctl enable iptables.service

 #說明:後續要添加端口,先重啓服務器再保存。

service iptables restart && service iptables save

 

四、關閉selinux

setenforce 0

sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config

cat /etc/selinux/config

注意:不要替換/etc/sysconfig/selinux文件,這是一個軟鏈接,不會生效。

 

1.3.5 設置主機名

#對每個節點進行設置主機名

vim /etc/hostname

k8smaster1

 

注意:aws修改centos主機名須要經過下面命令

hostnamectl set-hostname --static k8smaster

vim /etc/cloud/cloud.cfg    #最後一行添加

  preserve_hostname: true

#重啓機器

reboot

 

#對每一個節點配置IP和域名映射關係

vim /etc/hosts

172.31.50.170 k8smaster1
172.31.50.101 k8smaster2
172.31.58.221 k8smaster3
172.31.55.50 k8snode1
172.31.55.0 k8snode2

 

1.3.6 同步時間

yum install -y ntp

systemctl enable ntpd

systemctl start ntpd

timedatectl set-timezone Asia/Shanghai

timedatectl set-ntp yes

ntpq -p

 

1.4 部署etcd集羣

在K8s-master一、K8s-master二、K8s-master3三個節點上部署etcd節點,並組成集羣。

1.4.1 生成證書

在任意某一個etcd節點上安裝便可,主要使用生成的證書,其餘節點複製過去便可。使用cfssl來生成自簽證書。

一、先下載cfssl工具

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64

chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64

mv cfssl_linux-amd64 /usr/bin/cfssl

mv cfssljson_linux-amd64 /usr/bin/cfssljson

mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

 

二、建立三個文件

makdir etcd_ca

cd etcd_ca

# 建立 Etcd根證書配置文件

cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "www": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

 

# 建立 Etcd根證書請求文件

cat > ca-csr.json <<EOF
{
    "CN": "etcd CA",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF

 

# 建立 Etcd服務證書請求文件

cat > server-csr.json <<EOF
{
    "CN": "etcd",
    "hosts": [
    "172.31.50.170",
    "172.31.50.101",
    "172.31.58.221"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF

 

三、生成證書

# 生成 Etcd根證書

cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

# 生成 Etcd服務證書

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server

生成後能夠看到生成了4個pem文件

ls *pem

 

1.4.2 解壓etcd

如下部署步驟在規劃的三個etcd節點操做同樣,惟一不一樣的是etcd配置文件中的服務器IP要寫當前的。

二進制包下載地址:https://github.com/etcd-io/etcd/releases/

cd /usr/local/src/

wget https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz

mkdir /opt/etcd/{bin,cfg,ssl} -p

tar zxvf etcd-v3.3.12-linux-amd64.tar.gz

mv etcd-v3.3.12-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/

 

1.4.3 建立etcd配置文件

cat > /opt/etcd/cfg/etcd <<EOF
#[Member]
ETCD_NAME="etcd01"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://172.31.50.170:2380"
ETCD_LISTEN_CLIENT_URLS="https://172.31.50.170:2379"

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://172.31.50.170:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://172.31.50.170:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://172.31.50.170:2380,etcd02=https://172.31.50.101:2380,etcd03=https://172.31.58.221:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

注意:每一個節點上標黃的須要調整對應的值。

參數說明:

ETCD_NAME 節點名稱

ETCD_DATA_DIR 數據目錄

ETCD_LISTEN_PEER_URLS 集羣通訊監聽地址

ETCD_LISTEN_CLIENT_URLS 客戶端訪問監聽地址

ETCD_INITIAL_ADVERTISE_PEER_URLS 集羣通告地址

ETCD_ADVERTISE_CLIENT_URLS 客戶端通告地址

ETCD_INITIAL_CLUSTER 集羣節點地址

ETCD_INITIAL_CLUSTER_TOKEN 集羣Token

ETCD_INITIAL_CLUSTER_STATE 加入集羣的當前狀態,new是新集羣,existing表示加入已有集羣

 

1.4.4 systemd管理etcd

vim /usr/lib/systemd/system/etcd.service

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd
ExecStart=/opt/etcd/bin/etcd \
--name=${ETCD_NAME} \
--data-dir=${ETCD_DATA_DIR} \
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--initial-cluster=${ETCD_INITIAL_CLUSTER} \
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster-state=new \
--cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--peer-cert-file=/opt/etcd/ssl/server.pem \
--peer-key-file=/opt/etcd/ssl/server-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

 

1.4.5 拷貝證書

把剛纔生成的證書拷貝到配置文件中的位置。

#在生成證書節點上可直接執行:

cp ~/etcd_ca/*.pem /opt/etcd/ssl/

 

#其餘2個節點遠程複製過去:

scp ~/etcd_ca/*.pem root@172.31.50.101:/opt/etcd/ssl

scp ~/etcd_ca/*.pem root@172.31.55.50:/opt/etcd/ssl

 

1.4.6 開放防火牆端口

三個節點防火牆都開放端口:237九、2380端口

vim /etc/sysconfig/iptables

-A INPUT -p tcp -m state --state NEW -m tcp --dport 2379 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2380 -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

  

1.4.7 啓動etcd並設置自啓

systemctl daemon-reload

systemctl start etcd && systemctl enable etcd && systemctl status etcd

#注意:若是有問題,查看日誌:tail /var/log/messages

 

1.4.8 驗證集羣

/opt/etcd/bin/etcdctl \

--ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem \

--endpoints="https://172.31.50.170:2379,https://172.31.50.101:2379,https://172.31.58.221:2379" \

cluster-health

若是輸出上面截圖信息,就說明集羣部署成功。

 

1.4.9 etcdctl命令加入環境變量

vim /etc/profile

export PATH=/opt/etcd/bin:$PATH

#從新加載生效:

source /etc/profile

#下次登入還須要再次執行,因此把source命令添加到/etc/bashrc文件,這樣會爲每個用戶都執行這個命令。

echo "source /etc/profile" >> /etc/bashrc

 

1.5 Master節點部署組件

在部署Kubernetes以前必定要確保etcd是正常工做的,無特殊說明則需在三個master節點上操做。

1.5.1 生成證書

以前在master1節點的根目錄etcd_ca下生成過etcd的證書,爲了不證書混亂,在根目錄下新建目錄存放新的證書。

cd

mkdir k8s_ca

cd k8s_ca/

 

一、生成CA證書

cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF
cat > ca-csr.json <<EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

#執行下面命令生成

cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

  

二、生成apiserver證書

cat > server-csr.json <<EOF
{
    "CN": "kubernetes",
    "hosts": [
      "10.0.0.1",
      "127.0.0.1",
      "k8s-api-6443-c8528735cd54031c.elb.cn-north-1.amazonaws.com.cn",
      "172.31.50.170",
      "172.31.50.101",
      "172.31.58.221",
      "kubernetes",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

說明:10段爲虛擬IP段,還需添加上負載均衡IP(aws則須要先配置好1.5節內容),以及apiserver集羣IP。

 

#執行下面命令生成

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

 

三、生成kube-proxy證書

cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

 

#執行下面命令生成

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

 

四、生成admin證書

cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF

說明:後續 kube-apiserver 使用 RBAC 對客戶端(如 kubelet、kube-proxy、Pod)請求進行受權;kube-apiserver 預約義了一些 RBAC 使用的 RoleBindings,如 cluster-admin 將 Group system:masters 與 Role cluster-admin 綁定,該 Role 授予了調用kube-apiserver 的全部 API的權限;O 指定該證書的 Group 爲 system:masters,kubelet 使用該證書訪問 kube-apiserver 時 ,因爲證書被 CA 簽名,因此認證經過,同時因爲證書用戶組爲通過預受權的 system:masters,因此被授予訪問全部 API 的權限;

注意:這個admin 證書,是未來生成管理員用的kube config 配置文件用的,如今咱們通常建議使用RBAC 來對kubernetes 進行角色權限控制,kubernetes 將證書中的CN 字段做爲User,O 字段做爲 Group。

 

#執行下面命令生成

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin

  

五、查看生成的證書

最終生成8個文件

admin-key.pem  admin.pem  ca-key.pem  ca.pem  kube-proxy-key.pem  kube-proxy.pem  server-key.pem  server.pem

 

 

1.5.2 部署apiserver組件

此章節在全部master節點上操做。

下載二進制包頁面:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md

下載這個包(kubernetes-server-linux-amd64.tar.gz)就夠了,包含了所需的全部組件。地址:https://storage.googleapis.com/kubernetes-release/release/v1.14.1/kubernetes-server-linux-amd64.tar.gz

或者用上傳的七牛雲:https://img.yiyao.cc/kubernetes-server-linux-amd64.tar.gz

 

一、拷貝證書

mkdir /opt/kubernetes/{bin,cfg,ssl} -p

#拷貝證書

cp *pem /opt/kubernetes/ssl

#master2節點遠程複製過去:

scp *pem root@172.31.50.101:/opt/kubernetes/ssl

 

二、解壓文件

cd /usr/local/src

tar zxvf kubernetes-server-linux-amd64.tar.gz

cd kubernetes/server/bin

cp kube-apiserver kube-scheduler kube-controller-manager kubectl /opt/kubernetes/bin

 

三、建立token文件

cat > /opt/kubernetes/cfg/token.csv <<EOF
bd41d77ac7cad4cfaa27f6403b1ccf16,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF

說明:

第一列:隨機32位字符串,可本身命令生成:head -c 16 /dev/urandom | od -An -t x | tr -d ' '

第二列:用戶名

第三列:UID

第四列:用戶組

 

四、建立apiserver配置文件

配置好前面生成的證書,確保能鏈接etcd;address地址改爲當前節點的IP。

vim /opt/kubernetes/cfg/kube-apiserver

KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://172.31.50.170:2379,https://172.31.50.101:2379,https://172.31.58.221:2379 \
--bind-address=172.31.50.170 \
--secure-port=6443 \
--advertise-address=172.31.50.170 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/16 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth \
--token-auth-file=/opt/kubernetes/cfg/token.csv \
--service-node-port-range=30000-50000 \
--tls-cert-file=/opt/kubernetes/ssl/server.pem  \
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--kubelet-client-certificate=/opt/kubernetes/ssl/admin.pem \
--kubelet-client-key=/opt/kubernetes/ssl/admin-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem"

 #參數說明:

--logtostderr 啓用日誌

---v 日誌等級

--etcd-servers etcd集羣地址

--bind-address 監聽地址

--secure-port https安全端口

--advertise-address 集羣通告地址

--allow-privileged 啓用受權

--service-cluster-ip-range Service虛擬IP地址段

--enable-admission-plugins 准入控制模塊

--authorization-mode 認證受權,啓用RBAC受權和節點自管理

--enable-bootstrap-token-auth 啓用TLS bootstrap功能,後面會講到

--token-auth-file token文件

--service-node-port-range Service Node類型默認分配端口範圍

  

五、systemd管理apiserver

vim /usr/lib/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver
ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

 

 六、啓動apiserver

systemctl daemon-reload

systemctl enable kube-apiserver

systemctl restart kube-apiserver

systemctl status kube-apiserver

 

七、開放防火牆端口

kube-apiserver默認啓動兩個端口644三、8080

vim /etc/sysconfig/iptables

-A INPUT -p tcp -m state --state NEW -m tcp --dport 6443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

 

1.5.3 部署schduler組件

一、建立schduler配置文件

vim /opt/kubernetes/cfg/kube-scheduler

KUBE_SCHEDULER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \
--leader-elect"

#參數說明:

--master 鏈接本地apiserver

--leader-elect 當該組件啓動多個時,自動選舉(HA)

 

二、systemd管理schduler組件

vim /usr/lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

 

 三、啓動schduler

systemctl daemon-reload

systemctl enable kube-scheduler

systemctl restart kube-scheduler

systemctl status kube-scheduler

 

四、開放防火牆端口

schduler默認啓動端口10251

vim /etc/sysconfig/iptables

-A INPUT -p tcp -m state --state NEW -m tcp --dport 10251 -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

  

1.5.4 部署controller-manager組件

一、建立controller-manager配置文件

vim /opt/kubernetes/cfg/kube-controller-manager

KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \
--v=4 \
--master=127.0.0.1:8080 \
--leader-elect=true \
--address=127.0.0.1 \
--service-cluster-ip-range=10.0.0.0/16 \
--cluster-cidr=10.10.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem"

 

二、systemd管理controller-manager組件

vim /usr/lib/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
 
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager
ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

 

三、啓動controller-manager

systemctl daemon-reload

systemctl enable kube-controller-manager

systemctl restart kube-controller-manager

systemctl status kube-controller-manager

 

四、開放防火牆端口

schduler默認啓動端口10257

vim /etc/sysconfig/iptables

-A INPUT -p tcp -m state --state NEW -m tcp --dport 10257 -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

 

1.5.5 查看集羣組件狀態

/opt/kubernetes/bin/kubectl get cs

如上輸出說明組件都正常。另外一個Master節點部署方式同樣。

 

能夠把kubectl命令加入到環境變量

vim /etc/profile

export PATH=/opt/kubernetes/bin:$PATH

#從新加載生效

source /etc/profile

 

1.6 Master高可用

所謂的Master HA,其實就是APIServer的HA,Master的其餘組件controller-manager、scheduler都是能夠經過etcd作選舉(--leader-elect),而APIServer設計的就是可擴展性,因此作到APIServer很容易,只要前面加一個負載均衡輪訓轉發請求便可。若是是aws能夠採用負載均衡器實現,若是是實體機能夠採用Haproxy+keeplive實現。下面分別對這兩種方法進行驗證。

1.6.1 方法一:aws負載均衡器

一、配置aws負載均衡

二、配置路由

 

三、配置路由,選擇實例中的6443端口

 

四、註冊目標,選擇3個master實例

 

五、下一步審覈便可,最後會建立一個lb,而且會分配到一個域名

 

 

六、本地用tcping命令測試,可發現已經代理了6443端口

tcping k8s-api-6443-c8528735cd54031c.elb.cn-north-1.amazonaws.com.cn 6443

後續kubelet指定apiserver的地址時候,能夠寫該域名。

 

1.6.2 方法二:Haproxy+keepalive

在全部Master節點上部署Haproxy+keepalive。(適應於非雲平臺部署,因雲平臺不支持keepalive)

 一、部署haproxy

全部master節點上部署,配置保持同樣。

1)安裝haproxy

yum -y install haproxy

 

2)修改配置文件

cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg-back

vim /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats

defaults
    mode                    tcp
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend  main *:16443
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js
    use_backend static          if url_static
    default_backend             kube-apiserver

backend static
    balance     roundrobin
    server      static 127.0.0.1:4331 check

backend kube-apiserver
    balance     roundrobin
    server  matser1 172.31.50.170:6443 check
    server  master2 172.31.50.101:6443 check

#注意:修改標紅的地方

一、defaults 模塊中的 mode http 要改成 tcp(或者在下面的 frontend 和 backend 模塊中單獨定義 mode tcp )若是不改,後續 kubectl get node 會處於 NotReady 狀態。

二、frontend 端口需指定非 6443 端口,要否則其餘 master 節點會啓動異常(若是 haproxy 單獨主機,則可用 6443 端口)

  

說明:配置文件能夠拷貝其餘節點,配置文件保持同樣。

 

3)啓動haproxy

systemctl start haproxy

systemctl enable haproxy

systemctl status haproxy

 

4)配置防火牆

vim /etc/sysconfig/iptables

-A INPUT -p tcp -m state --state NEW -m tcp --dport 16443 -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

  

二、 部署keepalive

1)安裝keepalive

yum install -y keepalived

 

2)修改配置文件

cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf-back

vim /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   router_id LVS_1
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.10.24/24
    }
}

 說明:

一、global_defs 只保留 router_id(每一個節點都不一樣);

二、修改 interface(vip綁定的網卡),及 virtual_ipaddress(vip地址及掩碼長度);

三、刪除後面的示例

四、其餘節點只需修改 state 爲 BACKUP,優先級 priority 低於100便可。

 

3)啓動keeplive

systemctl start keepalived

systemctl enable keepalived

systemctl status keepalived

 

4)配置防火牆

防火牆要對vrrp協議進行開放

vim /etc/sysconfig/iptables

-A INPUT -p vrrp -j ACCEPT

#重啓防火牆

service iptables restart && service iptables save

 

5)查看狀態

ip addr show ens33

能夠看到vip只在一臺機器上;若是兩個機器都有vip,多是防火牆攔截了vrrp協議。

 

1.7 Node節點部署組件

Master apiserver啓用TLS認證後,Node節點kubelet組件想要加入集羣,必須使用CA簽發的有效證書才能與apiserver通訊,當Node節點不少時,簽署證書是一件很繁瑣的事情,所以有了TLS Bootstrapping機制,kubelet會以一個低權限用戶自動向apiserver申請證書,kubelet的證書由apiserver動態簽署。

1.7.1 認證流程

認證大體工做流程如圖所示:

 

 

1.7.2 用戶綁定系統集羣角色

在msater1上面執行,將kubelet-bootstrap用戶綁定到系統集羣角色:

/opt/kubernetes/bin/kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap

 

 

1.7.3 建立kubeconfig文件

在mster1生成kubernetes證書的目錄下執行如下命令生成kubeconfig文件,其餘節點拷貝過去便可。

cd /root/k8s_ca/

一、建立bootstrapping kubeconfig文件

1)指定apiserver 內網負載均衡地址端口(vip:port),以及token值

KUBE_APISERVER="https://k8s-api-6443-c8528735cd54031c.elb.cn-north-1.amazonaws.com.cn:6443"
BOOTSTRAP_TOKEN=bd41d77ac7cad4cfaa27f6403b1ccf16

說明: KUBE_APISERVER 參數對應的就是 AWS 中設置的負載均衡地址,或者對應 keepalive 的 vip 地址。

 

2)設置集羣參數

/opt/kubernetes/bin/kubectl config set-cluster kubernetes \
--certificate-authority=./ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig

 

3)設置客戶端認證參數

/opt/kubernetes/bin/kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=bootstrap.kubeconfig

 

4)設置上下文參數

/opt/kubernetes/bin/kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig

 

5)設置默認上下文

/opt/kubernetes/bin/kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

 

二、建立kube-proxy kubeconfig文件

1)設置集羣參數

/opt/kubernetes/bin/kubectl config set-cluster kubernetes \
--certificate-authority=./ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig

 

2)設置客戶端認證參數

/opt/kubernetes/bin/kubectl config set-credentials kube-proxy \
--client-certificate=./kube-proxy.pem \
--client-key=./kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig

 

3)設置上下文參數

/opt/kubernetes/bin/kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig

 

4)設置默認上下文

/opt/kubernetes/bin/kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

 

三、查看生成的kubeconfig文件

ls *kubeconfig

bootstrap.kubeconfig  kube-proxy.kubeconfig

 

四、拷貝kubeconfig文件

將這兩個文件拷貝到Node節點/opt/kubernetes/cfg目錄下。

須要在node節點上新建目錄

mkdir /opt/kubernetes/{bin,cfg,ssl} -p

scp *kubeconfig root@172.31.55.50:/opt/kubernetes/cfg

scp *kubeconfig root@172.31.55.0:/opt/kubernetes/cfg

  

1.7.4 Node節點安裝Docker

在全部node節點安裝docker。

yum install -y yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

yum install docker-ce -y

systemctl start docker

systemctl enable docker

 

注意:得提早安裝好docker環境,要否則kubelet啓動不起來。

 

1.7.5 部署kubelet組件

無特殊說明,則默認在全部node節點上都部署。

一、拷貝kubelet和kube-proxy文件

從msater1上下載解壓的二進制包中的kubelet和kube-proxy拷貝到node節點的/opt/kubernetes/bin目錄下。

cd /usr/local/src

wget https://img.yiyao.cc/kubernetes-server-linux-amd64.tar.gz

tar -zxvf kubernetes-server-linux-amd64.tar.gz

cd kubernetes/server/bin

scp kubelet kube-proxy root@172.31.55.50:/opt/kubernetes/bin

scp kubelet kube-proxy root@172.31.55.0:/opt/kubernetes/bin

 

二、建立kubelet配置文件

vim /opt/kubernetes/cfg/kubelet

KUBELET_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=k8snode1 \
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \
--config=/opt/kubernetes/cfg/kubelet.config \
--cert-dir=/opt/kubernetes/ssl \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"

 而且須要拷貝ca證書到/opt/kubernetes/ssl目錄下。

參數說明:

--hostname-override 在集羣中顯示的主機名

--kubeconfig 指定kubeconfig文件位置,會自動生成

--bootstrap-kubeconfig 指定剛纔生成的bootstrap.kubeconfig文件

--cert-dir 頒發證書存放位置

--pod-infra-container-image 管理Pod網絡的鏡像

  

三、建立kubelet.config配置文件

注意格式縮進

vim /opt/kubernetes/cfg/kubelet.config

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 172.31.55.50
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS: ["10.0.0.2"]
clusterDomain: cluster.local.
failSwapOn: false
authentication:
  anonymous:
    enabled: true
  webhook:
    enabled: false

 

四、systemd管理kubelet組件

vim /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet
ExecStart=/opt/kubernetes/bin/kubelet $KUBELET_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

 

五、啓動kubelet組件

systemctl daemon-reload

systemctl enable kubelet    #開機自啓

systemctl restart kubelet    #啓動

systemctl status kubelet    #啓動狀態

 

會佔用10250端口(須要在iptables設置開放,協議爲tcp),要否則進入容器會報錯:

Error from server: error dialing backend: dial tcp 172.31.55.50:10250: connect: no route to host

這裏是把全部 node 節點的iptables配置文件都清空的,默認全部端口開放,因此不用單獨設置。

  

六、在Master審批Node加入集羣

啓動後還沒加入到集羣中,須要手動容許該節點才能夠。

1)在Master節點查看請求籤名的Node:

/opt/kubernetes/bin/kubectl get csr

能夠看到有兩個節點的簽名請求,若是執行命令後提示:No resources found,可去node節點查看messages日誌。

 

2)在Master節點批准簽名

/opt/kubernetes/bin/kubectl certificate approve node-csr-SJvxb_b-sBqfsLo-ILzaQm_6S9DH_w3THpLGCLNkLDU

/opt/kubernetes/bin/kubectl certificate approve node-csr-bF-v5M0Nv3niDVVEGf1YdlwYvRoRrjhR82jlPiXiOvU

 

 

3)查看簽名狀態

/opt/kubernetes/bin/kubectl get node

狀態都爲Ready。

  

1.7.6 部署kube-proxy組件

在全部node節點上部署。

一、建立kube-proxy配置文件

vim /opt/kubernetes/cfg/kube-proxy

KUBE_PROXY_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=k8snode1 \
--cluster-cidr=10.10.0.0/16 \
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"

注意:cluster-cidr不能與service-cidr還有主機的cidr網段重疊。

 

二、systemd管理kube-proxy組件

vim /usr/lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Proxy
After=network.target

[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

 

三、啓動kube-proxy組件

systemctl daemon-reload

systemctl enable kube-proxy

systemctl restart kube-proxy

systemctl status kube-proxy

 

#會佔用兩個端口:1024九、10256

 

1.7.7 確認node可以訪問443端口

tcping 10.0.0.1 443

到此部署node完成。

 

1.8 部署Calico網絡

若無特殊說明,都需在master1節點上操做。配置參考:https://www.jianshu.com/p/5e9e2e5312d9

1.8.1 工做原理

一、特色優點

1) 純三層的SDN 實現,它基於BPG 協議和Linux自身的路由轉發機制,不依賴特殊硬件,容器通訊也不依賴iptables NAT(使用直接路由方式實現通行)或Tunnel 等技術,帶寬性能接近主機。

2)可以方便的部署在物理服務器、虛擬機或者容器環境下。

3)同時calico自帶的基於iptables的ACL管理組件很是靈活,可以知足比較複雜的安全隔離需求。支持Kubernetes networkpolicy概念

4)容器間網絡三層隔離,無須要擔憂arp風暴

5)自由控制的policy規則

6)經過iptables和kernel包轉發,效率高,損耗低

 

二、calico組件

1)Felix:主要負責路由配置以及ACLS規則的配置以及下發,它存在在每一個node節點上。

2)etcd:分佈式鍵值存儲,主要負責網絡元數據一致性,確保Calico網絡狀態的準確性,能夠與kubernetes共用;

3)BGPClient(BIRD), 主要負責把 Felix寫入 kernel的路由信息分發到當前 Calico網絡,確保 workload間的通訊的有效性;

4)BGPRoute Reflector(BIRD), 大規模部署時使用,摒棄全部節點互聯的mesh模式,經過一個或者多個 BGPRoute Reflector 來完成集中式的路由分發;

以下圖:

 

  

1.8.2 配置calico

部署calico須要在kubernetes集羣部署好後操做,只需在master1上操做

一、下載yaml文件

mkdir /opt/calico/{bin,deploy} -p

cd /opt/calico/deploy

wget https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/calico.yaml

 

二、配置calico

部署以前須要檢查3處

1)配置ConfigMap中etcd集羣etcd_endpoints

etcd_endpoints: "https://172.31.50.170:2379,https://172.31.50.101:2379,https://172.31.58.221:2379"

 

2)配置Calico訪問etcd集羣的TLS證書,默認已經給出了訪問etcd的TLS文件所在容器路徑了,填進去便可(注意:此配置爲容器內部讀取的變量,因此證書路徑爲容器路徑,而不是宿主機路徑,不要修改成別的路徑。)。

etcd_ca: "/calico-secrets/etcd-ca"
etcd_cert: "/calico-secrets/etcd-cert"
etcd_key: "/calico-secrets/etcd-key"

 

3)在Secret部分中,是採用建立secret的方式來配置TLS文件,在這裏咱們改用hostPath掛載TLS文件方式

#註釋掉的Secret部分的TLS部分,默認爲註釋可不用改

 

#設置calico-node以hostpath的方式來掛載TLS文件,找到DaemonSet部分,設置爲以下:

        - name: etcd-certs
          hostPath:
            path: /opt/etcd/ssl

 

#設置calico-kube-controllers以hostpath掛載TLS文件,找到Deployment部分,設置爲以下:

        - name: etcd-certs
          hostPath:
            path: /opt/etcd/ssl

 

4)修改deamonset部分CALICO_IPV4POOL_CIDR變量

value: "10.10.0.0/16"

 

說明:

一、CALICO_IPV4POOL_CIDR: Calico IPAM的IP地址池,Pod的IP地址將從該池中進行分配(後續須要更改這個IP池,可參考1.8.9小節)。這個值須要同kube-controller-manager和kebe-proxy定義的--cluster-cidr值一致,可是得和apiserver中的service-cluster-ip-range值不一樣。

二、ALICO_IPV4POOL_IPIP:是否啓用IPIP模式,啓用IPIP模式時,Calico將在node上建立一個tunl0的虛擬隧道。

三、FELIX_LOGSEVERITYSCREEN: 日誌級別。

四、IP Pool可使用兩種模式:BGP或IPIP。使用IPIP模式時,設置 CALICO_IPV4POOL_IPIP="always",不使用IPIP模式時,設置爲"off",此時將使用BGP模式。

五、IPIP:ipip是在宿主機網絡不徹底支持bgp時,一種妥協的overlay機制,在宿主機建立1個」tunl0」虛擬端口;設置爲false時,路由即純bgp模式,理論上ipip模式的網絡傳輸性能低於純bgp模式;設置爲true時,又分ipip always模式(純ipip模式)與ipip cross-subnet模式(ipip-bgp混合模式),後者指「同子網內路由採用bgp,跨子網路由採用ipip」

 

1.8.3 修改kubelet

在每一個node節點上操做

#kubelet啓動服務中增長--network-plugin、--cni-conf-dir、--cni-bin-dir三個配置參數

vim /opt/kubernetes/cfg/kubelet

--network-plugin=cni \
--cni-conf-dir=/etc/cni/net.d \
--cni-bin-dir=/opt/cni/bin \

#重啓kubelet 

systemctl daemon-reload && systemctl restart kubelet && systemctl status kubelet

 

1.8.4 拷貝etcd的TLS受權文件

在各node節點操做,把master上的etcd證書所有複製到全部node的目錄下(步驟略),而後重命名一下(這裏複製一份,由於後面安裝calicoctl工具須要原來的證書名字):

mkdir /opt/etcd/ssl -p

cd /opt/etcd/ssl

cp ca.pem etcd-ca

cp server-key.pem etcd-key

cp server.pem etcd-cert

 

1.8.5 部署calico組件

#部署calico

kubectl apply -f calico.yaml

 

#查看calico服務

calico-node用的是daemonset,會在每一個node上啓動; calico-kube-controllers用的是Deployment,會在某個node啓動。

kubectl get deployment,pod -n kube-system

 

#同時在node節點上能夠看到已經生成了tunl0隧道網卡

 

1.8.6 驗證網絡功能

新建一個nginx pod

cat > my-nginx.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: my-nginx
  template:
    metadata:
      labels:
        k8s-app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.9
        ports:
        - containerPort: 80
EOF

#建立pod

kubectl create -f my-nginx.yaml

#建立my-nginx服務

kubectl expose deploy my-nginx

#查看pod

kubectl get svc,pod --all-namespaces -o wide

看到能夠給pod分配到IP,說明calico配置好了。(默認全部的pod都是互通的,包括跨node。能夠用 route -n 查看有通往其餘 node 的 tunl0 路由)

 

1.8.7 安裝管理工具calicoctl

在全部master和node節點上操做

一、下載calicoctl

cd /opt/calico/bin   (從節點:mkdir -p /opt/calico/bin && cd /opt/calico/bin)

wget https://github.com/projectcalico/calicoctl/releases/download/v3.6.0/calicoctl

chmod +x calicoctl

 

#添加calicoctl 命令加入到環境變量

echo "export PATH=/opt/calico/bin:\$PATH" >>/etc/profile

#從新加載生效

source /etc/profile

 

二、編寫calicoctl的配置文件

#默認爲下面的路徑,不要改動

mkdir /etc/calico

vim /etc/calico/calicoctl.cfg

apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "etcdv3"
  etcdEndpoints: "https://172.31.50.170:2379,https://172.31.50.101:2379,https://172.31.58.221:2379"
  etcdKeyFile: "/opt/etcd/ssl/server-key.pem"
  etcdCertFile: "/opt/etcd/ssl/server.pem"
  etcdCACertFile: "/opt/etcd/ssl/ca.pem"

 

三、查看calico狀態

#查看已註冊的節點列表

calicoctl get node

#查看默認IP池

calicoctl get ippool -o wide

#查看節點狀態爲Established(這個必需要在每一個node節點上安裝calicoctl,在node上執行,而且只能看到非本節點的)。

calicoctl node status

 

到此部署calico完成。

 

 

1.8.8 更換IP池方法

參考官網:https://docs.projectcalico.org/v3.6/networking/changing-ip-pools

一、前提條件

在Kubernetes中,確保如下全部三個參數必須等於或包含Calico IP池CIDR

kube-apiserver: --pod-network-cidr

kube-proxy: --cluster-cidr

kube-controller-manager: --cluster-cidr

說明:我設置了apiserver後,apiserver啓動失敗,暫不設置。

 

二、添加新的IP池

#查看默認的IP池

calicoctl get ippool -o wide

#建立新的IP池

calicoctl create -f -<<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: new-pool
spec:
  cidr: 10.10.0.0/16
  ipipMode: Always
  natOutgoing: true
EOF

 

#查看到有2個IP池

 

三、禁用舊的IP池

首先將IP池定義保存到本地磁盤

cd /opt/calico/deploy

calicoctl get ippool -o yaml > pool.yaml

 

#編輯pool.yaml文件,添加disabled: true到default-ipv4-ippoolIP池,最終文件內容以下:

apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: 2019-04-29T03:22:59Z
    name: default-ipv4-ippool
    resourceVersion: "82916"
    uid: 16db9294-6a2e-11e9-b48f-0225173d78b8
  spec:
    blockSize: 26
    cidr: 10.0.0.0/24
    ipipMode: Always
    natOutgoing: true
    nodeSelector: all()
    disabled: true - apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: 2019-05-06T05:32:27Z
    name: new-pool
    resourceVersion: "1086435"
    uid: 55a21a46-6fc0-11e9-bf99-02b325080bdc
  spec:
    blockSize: 26
    cidr: 10.10.0.0/16
    ipipMode: Always
    natOutgoing: true
    nodeSelector: all()
kind: IPPoolList
metadata:
  resourceVersion: "1086435"

#應用更改

calicoctl apply -f pool.yaml

 

#再查看IP池狀態

calicoctl get ippool -o wide

 

四、從新建立從舊IP池分配地址的全部現有工做負載

#查看現有的工做負載

kubectl get svc,pod --all-namespaces -o wide

 

#從新建立全部現有工做負載

kubectl delete pod -n online online-nginx-776bbdf4f8-2fl95

kubectl delete pod -n online online-nginx-776bbdf4f8-sznmg

  

五、刪除舊的IP池

calicoctl delete pool default-ipv4-ippool

  

1.8.9 卸載calico方法

一、master上執行刪除pod

kubectl delete -f calico.yaml

二、node上刪除ipip模塊(對應的網卡和路由也會被刪除)

modprobe -r ipip

三、node上刪除生成的文件

rm -rf /etc/cni/net.d/ && rm -rf /opt/cni/bin/

四、重啓node

reboot

 

 

2、部署CoreDNS

在master1上操做,參考:https://www.zrq.org.cn/post/k8s%E9%83%A8%E7%BD%B2coredns/

2.1 下載配置文件

從官網下載配置文件(https://github.com/coredns/deployment/tree/master/kubernetes),找到 coredns.yam.sed 和 deploy.sh 兩個文件,下載後存放在下面的新建目錄下

mkdir /opt/coredns  && cd /opt/coredns/

wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh

wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed

chmod +x deploy.sh

 

2.2 修改部署文件

因爲是二進制部署的集羣,不包含kube-dns,故不需從kube-dns轉到coredns。

一、先查看集羣的CLUSTERIP網段

kubectl get svc

 

二、修改部署文件

修改$DNS_DOMAIN、$DNS_SERVER_IP變量爲實際值,並修改image後面的鏡像。

這裏直接用deploy.sh腳本進行修改:

./deploy.sh -s -r 10.0.0.0/16 -i 10.0.0.2 -d cluster.local > coredns.yaml

注意:網段爲10.0.0.0/16(同apiserver定義的service-cluster-ip-range值,非kube-proxy中的cluster-cidr值),DNS的地址設置爲10.0.0.2

 

三、修改先後的文件對比

diff coredns.yaml coredns.yaml.sed

 附:生成的 coredns.yaml文件,注意標黃位置。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: coredns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  - services
  - pods
  - namespaces
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:coredns
subjects:
- kind: ServiceAccount
  name: coredns
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local 10.0.0.0/16 {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: "CoreDNS"
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        beta.kubernetes.io/os: linux
      containers:
      - name: coredns
        image: coredns/coredns:1.5.0
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.0.0.2
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP

#說明:

$DNS_DOMAIN 被修改成:cluster.local

image 這邊用的是:coredns/coredns:1.5.0

$DNS_SERVER_IP 被修改成:10.0.0.2 

 

2.3 部署coredns

#部署

kubectl create -f coredns.yaml

#查看

kubectl get svc,pod -n kube-system

 

2.4 修改kubelet的dns服務參數

在全部node節點上操做,添加如下參數

vim /opt/kubernetes/cfg/kubelet

--cluster-dns=10.0.0.2 \
--cluster-domain=cluster.local. \
--resolv-conf=/etc/resolv.conf \

#重啓kubelet 並查看狀態

systemctl daemon-reload && systemctl restart kubelet && systemctl status kubelet

 

2.5 驗證CoreDNS服務解析

2.5.1 使用dnstools測試效果

#在master上操做,注意:busybox不能用高版本,要用低版本測試。

kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh

nslookup kubernetes.default

nslookup www.baidu.com

輸出結果如上,說明coredns能夠解析成功。

cat /etc/resolv.conf

如上,每一個pod都會在resolv.conf文件中聲明dns地址。

 

2.5.2 測試namespace域名互通

1.8.7小節已經在默認namespace:default中建立好了my-nginx,如今咱們新建一個namespace:online,並建立online-nginx服務

一、建立namespace

kubectl create namespace online

二、部署online-nginx

cat >online-nginx.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: online-nginx
  namespace: online
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: online-nginx
  template:
    metadata:
      labels:
        k8s-app: online-nginx
    spec:
      containers:
      - name: online-nginx
        image: nginx:1.9
        ports:
        - containerPort: 80
EOF

kubectl create -f online-nginx.yaml

kubectl expose deploy online-nginx -n online

 

三、運行curl工具測試

kubectl run curl --image=radial/busyboxplus:curl --namespace="online" --restart=Never --rm -it

nslookup kubernetes.default

curl my-nginx.default

curl online-nginx

說明:也能夠指定namespace,訪問以前的my-nginx域名地址,也能夠訪問同一namespace的pod。說明在不一樣的namespace上是互通的。

 

 

2.6 訪問容器報錯解決

[root@centos7 ~]# kubectl get pods

NAME                    READY   STATUS    RESTARTS   AGE

nginx-dbddb74b8-s7lp5   1/1     Running   1          22h

nginx-dbddb74b8-znxz5   1/1     Running   1          22h

 

以下發現執行查看資源報錯,不能進入容器。報錯:

[root@centos7 ~]# kubectl exec -it nginx-dbddb74b8-s7lp5 sh

error: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)

緣由:2.7.4中kubelet.config定義了:沒有進行身份驗證方法的對kubelet的HTTPS端點的請求將被視爲匿名請求,並提供用戶名system:anonymous 和組system:unauthenticated。因此提示anonymous用戶沒有權限。

 

解決(官方推薦):啓動apiserver時指定admin帳戶證書受權

1)配置 kube-apiserver

vim /opt/kubernetes/cfg/kube-apiserver

--kubelet-client-certificate=/opt/kubernetes/ssl/admin.pem \
--kubelet-client-key=/opt/kubernetes/ssl/admin-key.pem \

#重啓 kube-apiserver

systemctl daemon-reload && systemctl restart kube-apiserver && systemctl status kube-apiserver

 

2)配置kubelet,從master複製apiserver中的ca證書到node上

vim /opt/kubernetes/cfg/kubelet

--client-ca-file=/opt/kubernetes/ssl/ca.pem \

#重啓 kube-apiserver

systemctl daemon-reload && systemctl restart kubelet && systemctl status kubelet

 

3、部署高可用Ingress

3.1 Ingress簡介

3.1.1需求

coredns是實現pods之間經過域名訪問,若是外部須要訪問service服務,需訪問對應的NodeIP:Port。可是因爲NodePort須要指定宿主機端口,一旦服務多起來,多個端口就難以管理。那麼,這種狀況下,使用Ingress暴露服務更加合適。

 

3.1.2 Ingress組件說明

使用Ingress時通常會有三個組件:反向代理負載均衡器、Ingress Controller、Ingress

一、反向代理負載均衡器

反向代理負載均衡器很簡單,說白了就是 nginx、apache 等中間件,新版k8s已經將Nginx與Ingress Controller合併爲一個組件,因此Nginx無需單獨部署,只須要部署Ingress Controller便可。在集羣中反向代理負載均衡器能夠自由部署,可使用 Replication Controller、Deployment、DaemonSet 等等方式

二、Ingress Controller

Ingress Controller 實質上能夠理解爲是個監視器,Ingress Controller 經過不斷地跟 kubernetes API 打交道,實時的感知後端 service、pod 等變化,好比新增和減小 pod,service 增長與減小等;當獲得這些變化信息後,Ingress Controller 再結合下文的 Ingress 生成配置,而後更新反向代理負載均衡器,並刷新其配置,達到服務發現的做用

三、Ingress

Ingress 簡單理解就是個規則定義;好比說某個域名對應某個 service,即當某個域名的請求進來時轉發給某個 service;這個規則將與 Ingress Controller 結合,而後 Ingress Controller 將其動態寫入到負載均衡器配置中,從而實現總體的服務發現和負載均衡

總體關係以下圖所示:

 

從上圖中能夠很清晰的看到,實際上請求進來仍是被負載均衡器攔截,好比 nginx,而後 Ingress Controller 經過跟 Ingress 交互得知某個域名對應哪一個 service,再經過跟 kubernetes API 交互得知 service 地址等信息;綜合之後生成配置文件實時寫入負載均衡器,而後負載均衡器 reload 該規則即可實現服務發現,即動態映射。

 

3.1.3 Nginx-Ingress工做原理

ingress controller經過和kubernetes api交互,動態的去感知集羣中ingress規則變化;而後讀取它,按照自定義的規則,規則就是寫明瞭哪一個域名對應哪一個service,生成一段nginx配置;再寫到nginx-ingress-control的pod裏,這個Ingress controller的pod裏運行着一個Nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中;而後reload一下使配置生效。以此達到域名分配置和動態更新的問題。

 

說明:基於nginx服務的ingress controller根據不一樣的開發公司,又分爲:

k8s社區的ingres-nginx(https://github.com/kubernetes/ingress-nginx)

nginx公司的nginx-ingress(https://github.com/nginxinc/kubernetes-ingress)

 

3.2.4 Ingress Controller高可用架構

做爲集羣流量接入層,Ingress Controller的高可用性顯得尤其重要,高可用性首先要解決的就是單點故障問題,通常經常使用的是採用多副本部署的方式,咱們在Kubernetes集羣中部署高可用Ingress Controller接入層一樣採用多節點部署架構,同時因爲Ingress做爲集羣流量接入口,建議採用獨佔Ingress節點的方式,以免業務應用與Ingress服務發生資源爭搶。

 

如上述部署架構圖,由多個獨佔Ingress實例組成統一接入層承載集羣入口流量,同時可依據後端業務流量水平擴縮容Ingress節點。固然若是您前期的集羣規模並不大,也能夠採用將Ingress服務與業務應用混部的方式,但建議進行資源限制和隔離。

 

3.2 部署高可用Ingress

ingress的高可用的話,要能夠經過把nginx-ingress-controller運行到指定添加標籤的幾個node節點上,而後再把這幾個node節點加入到LB中,而後對應的域名解析到該LB便可實現ingress的高可用。(注意:添加標籤的節點數量要大於等於集羣Pod副本數,從而避免多個Pod運行在同一個節點上。不建議將Ingress服務部署到master節點上,儘可能選擇worker節點添加標籤。)

如下無特殊說明,都在master1上操做,參考:http://www.javashuo.com/article/p-zvducfkf-kr.html

3.2.1 給node添加標籤

我這裏在2個node上安裝nginx-ingress-controller,只需給這兩個node添加標籤

kubectl label node k8snode1 ingresscontroller=true

kubectl label node k8snode2 ingresscontroller=true

#查看標籤

kubectl get nodes --show-labels

 

附: 

#刪除標籤

kubectl label node k8snode1 ingresscontroller-

#更新標籤

kubectl label node k8snode1 ingresscontroller=false --overwrite

  

3.2.2 下載yaml部署文件

下載地址:https://github.com/kubernetes/ingress-nginx/tree/master/deploy,有以下幾個yaml文件,咱們只須要下載mandatory.yaml文件便可,它包含了其他4個文件的內容。

mkdir /opt/ingress && cd /opt/ingress/

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

 

3.2.3 修改yaml文件

一、修改Deployment爲DaemonSet,並註釋掉副本數

kind: DaemonSet #replicas: 1

說明:默認kind: Deployment,replicas: 1,即在1個節點上啓動1個ingress-nginx controller Pod,因此須要修成DaemonSet,即爲每個節點都啓動一個pod。

DaemonSet和Deployment區別:Deployment 部署的副本 Pod 會分佈在各個 Node 上,每一個 Node 均可能運行好幾個副本。DaemonSet 的不一樣之處在於:每一個 Node 上最多隻能運行一個副本。

 

二、啓用hostNetwork網絡,並指定運行節點

hostNetwork暴露ingress-nginx controller的相關業務端口到主機,這樣node節點主機所在網絡的其餘主機,均可以經過該端口訪問到此應用程序。

nodeSelector指定以前添加ingresscontroller=true標籤的node

      hostNetwork: true
      nodeSelector:
        ingresscontroller: 'true'

 

三、修改鏡像地址,默認的鏡像地址下載了幾個小時都沒下載好

registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.24.1

可提早在node上下載鏡像

 

3.2.4 部署ingress

#部署

kubectl create -f mandatory.yaml

#查看ingress-controller

kubectl get ds -n ingress-nginx

kubectl get pods -n ingress-nginx -o wide

 

踩坑:pod沒法建立,而且create的時候也沒有任何錯誤。

參考網上文章:https://www.liuyalei.top/1455.html 後,有提示報錯:Error creating: pods "nginx-ingress-controller-565dfd6dff-g977n" is forbidden: SecurityContext.RunAsUser is forbidden

解決:須要對準入控制器進行修改,取消SecurityContextDeny 的enable就行,而後重啓apiserver:

vim /opt/kubernetes/cfg/kube-apiserver

--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \

#重啓 kube-apiserver

systemctl daemon-reload && systemctl restart kube-apiserver && systemctl status kube-apiserver

 

3.3 驗證功能

3.3.1 建立測試用pod和server

vim nginx-static.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-static
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-static
  labels:
    name: nginx-static
spec:
  replicas: 1
  template:
    metadata:
      labels:
       name: nginx-static
    spec:
      containers:
       - name: nginx-static
         image: nginx:latest
         volumeMounts:
          - mountPath: /etc/localtime
            name: vol-localtime
            readOnly: true

         ports:
          - containerPort: 80
      volumes:
         - name: vol-localtime
           hostPath:
            path: /etc/localtime
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-static
  labels:
   name: nginx-static
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    name: http
  selector:
    name: nginx-static

#建立

kubectl create -f nginx-static.yaml

#查看服務和pod

能夠看到部署到了k8smaster2(172.31.50.101)上

 

3.3.2 配置ingress

vim nginx-static-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: submodule-checker-ingress
spec:
  rules:
  - host: nginx.weave.pub
    http:
      paths:
      - backend:
          serviceName: nginx-static
          servicePort: 80

#應用ingress規則

kubectl create -f nginx-static-ingress.yaml 

#查看ingress規則

kubectl get ingress -o wide

 

3.3.3 訪問

在其餘端訪問,須要修改hosts文件,好比修改master1的hosts,給ingress服務端的IP,指定到自定義的域名。

172.31.55.50 k8snode3 nginx.weave.pub

 #測試可否解析

curl nginx.weave.pub

 

訪問報錯:504 Gateway time out,這是由於nginx鏈接時間超時,默認是60s,設置大一點。

參考:https://github.com/kubernetes/ingress-nginx/issues/2007

解決:修改nginx-static-ingress.yaml文件,添加標紅處:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: submodule-checker-ingress
 annotations: kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "14400"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "14400"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "14400"
spec:
  rules:
  - host: nginx.weave.pub
    http:
      paths:
      - backend:
          serviceName: nginx-static
          servicePort: 80

從新應用 

kubectl apply -f nginx-static-ingress.yaml

  

3.4 總結

一、在實際應用場景,經常會把多個服務部署在不一樣的namespace,來達到隔離服務的目的,好比A服務部署在namespace-A,B服務部署在namespace-B。這種狀況下,就須要聲明Ingress-A、Ingress-B兩個Ingress分別用於暴露A服務和B服務,且Ingress-A必須處於namespace-A,Ingress-B必須處於namespace-B。不然Controller沒法正確解析Ingress的規則。

二、集羣內能夠聲明多個Ingress和多個Ingress Controller,一個Ingress Controller能夠監聽多個Ingress,Ingress和其定義的服務必須處於同一namespace。

三、快速擴容,隨着業務流量不斷增加,集羣規模不斷擴大,只須要簡單地經過打標的方式來快速擴容Ingress接入層;而後再把這幾個node節點加入到lb中,而後對應的域名解析到該lb便可實現ingress的高可用。

 

 到這裏ingress部署完成。

 

4、node增刪

4.1 增長node方法

4.1.1 基本設置

執行 1.3.4-1.3.6 步驟

  

4.1.2 配置kubelet組件

執行1.7.3~1.7.7,1.8.3-1.8.4,1.8.7,2.4後,還需操做以下:

複製matser上/opt/kubernetes/ssl/ca.pem,到node相同目錄

 

4.1.3 配置calico相關證書

複製matser上/opt/etcd/ssl/{ca.pem,server-key.pem,server.pem},到node相同目錄,並重命名node上的etcd證書名稱(calico網絡須要該證書)

cp ca.pem etcd-ca && cp server-key.pem etcd-key && cp server.pem etcd-cert

重啓kubelet組件

systemctl daemon-reload && systemctl restart kubelet && systemctl status kubelet

systemctl daemon-reload && systemctl restart kube-proxy && systemctl status kube-proxy

 

4.1.4 測試calico網絡正常

master節點新建測試文件

cat >> test-nginx.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: test-nginx
  template:
    metadata:
      labels:
        k8s-app: test-nginx
    spec:
      nodeSelector:
        kubernetes.io/hostname: "k8snode3"
      containers:
      - name: test-nginx
        image: nginx:1.9
        ports:
        - containerPort: 80
EOF

#建立pod

kubectl create -f test-nginx.yaml

#建立服務

kubectl expose deploy test-nginx

#查看狀態

kubectl get svc,pod --all-namespaces -o wide

 

若是異常,查看日誌

kubectl describe pod/test-nginx-747548b77d-8cs65

報錯: k8snode3  Failed create pod sandbox: rpc error: code = Unknown desc = [failed to set up sandbox container "360e03c13615b9ad0c1e6d9c7fca1b300311398c038ea6d6587d465fb956f250" network for pod "my-nginx-6ccc5d6cbd-q2v5w": NetworkPlugin cni failed to set up pod "my-nginx-6ccc5d6cbd-q2v5w_default" network: context deadline exceeded, failed to clean up sandbox container "360e03c13615b9ad0c1e6d9c7fca1b300311398c038ea6d6587d465fb956f250" network for pod "my-nginx-6ccc5d6cbd-q2v5w": NetworkPlugin cni failed to teardown pod "my-nginx-6ccc5d6cbd-q2v5w_default" network: context deadline exceeded]

解決:重啓該node節點可解決。

 

4.1.5 測試coredns正常

kubectl run curl --image=radial/busyboxplus:curl --restart=Never --rm -it

curl test-nginx.default

 

4.1.6 測試ingress正常

vim test-nginx-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-checker-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "14400"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "14400"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "14400"
spec:
  rules:
  - host: test-nginx.weave.pub
    http:
      paths:
      - backend:
          serviceName: test-nginx
          servicePort: 80

kubectl apply -f test-nginx-ingress.yaml

而後curl測試下

  

4.2 刪除node方法

kubectl get nodes

kubectl cordon k8s-node1    #設置不可調度

kubectl drain k8snode1 --ignore-daemonsets --delete-local-data      #驅離pod到其餘節點

kubectl get pod --all-namespaces -o wide |grep k8snode1      #查看是否還有pod

kubectl delete node k8snode1    #刪除節點

 

4.3 Node隔離與恢復

在硬件升級、硬件維護的狀況下,咱們須要將某些Node進行隔離,脫離k8s的調度範圍。k8s提供了一套機制,既能夠將Node歸入調度範圍,也能夠將Node脫離調度範圍。

kubectl cordon k8s-node1    #將k8s-node1節點設置爲不可調度模式

kubectl drain k8s-node1     #將當前運行在k8s-node1節點上的容器驅離

kubectl uncordon k8s-node1  #執行完維護後,將節點從新加入調度

  

4.4 刪除頑固namespace

檢查該namespace下是否還有資源:kubectl get all --namespace=ingress-nginx

刪除資源:kubectl delete pods <pod> --grace-period=0 --force

而後編輯namespace:kubectl edit ns ingress-nginx

註釋掉finalizers部分,保存即會刪除該ns

再次查看已被刪除:kubectl get ns

相關文章
相關標籤/搜索