還不會K8S嗎?先從kubeadm開始吧

東方雨傾發表於2020-05-24

kubeadm是Kubernetes官方提供的用於快速安裝Kubernetes叢集的工具,伴隨Kubernetes每個版本的釋出都會同步更新,kubeadm會對叢集配置方面的一些實踐做調整,通過實驗kubeadm可以學習到Kubernetes官方在叢集配置上一些新的最佳實踐。

在Kubernetes的文件Creating a single master cluster with kubeadm中已經給出了目前kubeadm的主要特性已經處於beta狀態了,在2018年將進入GA狀態,說明kubeadm離可以在生產環境中使用的距離越來越近了。

下面我將介紹一下kubeadm的安裝,比起k8s的二進位制安裝方式,kubeadm的安裝門檻較低,更容易上手。

1. 準備工作

1.1 機器準備

準備三臺Centos7.x虛擬機器,具體配置如下:

IP Role CPU Memory Hostname
192.168.199.231 master >= 2C >= 2G master
192.168.199.232 worker >= 2C >= 2G node1
192.168.199.233 worker >= 2C >= 2G node1

IP 根據你自己宿主機機器網段決定。

1.2 系統配置

1.2.1 主機名及域名解析

# 192.168.199.231上執行
hostnamectl set-hostname master

# 192.168.199.232上執行
hostnamectl set-hostname node1

# 192.168.199.233上執行
hostnamectl set-hostname node2

# 192.168.199.231、192.168.199.232、192.168.199.233三臺都執行
cat <<EOF>>/etc/hosts
192.168.199.231 master
192.168.199.232 node1
192.168.199.233 node2
EOF

設定完後,相互ping一下看看網路是否通。如:ping node1

1.2.2 免密登入

設定 master 可以無密碼登入所有節點的 root 賬戶:

## 第一步:在master節點執行,一路回車到底
ssh-keygen -t rsa

## 第二步:在master節點執行以下三句,然後分別輸入對應機器登入密碼
ssh-copy-id root@master
ssh-copy-id root@node1
ssh-copy-id root@node2

1.2.3 配置yum源

注意:所有虛擬機器都需要執行下面的操作

配置阿里軟體源(base和epel):

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

最後一句記得回車,配置完過後,可通過命令:

yum repolist

來檢視是否配置成功。如果出現如下資訊則表示成功:

  • base: mirrors.aliyun.com
  • extras: mirrors.aliyun.com
  • updates: mirrors.aliyun.com

配置國內Kubernetes源:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

配置docker源:

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

執行清理和更新:

yum clean all && yum makecache && yum update -y	# 第一次需要比較久的時間,去喝杯水休息休息

1.2.4 安裝必要依賴包

在三臺機器上執行命令:

yum install -y epel-release
yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget
/usr/sbin/modprobe ip_vs # 這一句記得回車

ipvs 依賴 ipset

ntp 保證各機器系統時間同步;

1.2.5 關閉防火牆、SELinux、Swap分割槽

注意:所有虛擬機器都需要執行下面的操作

關閉防火牆:

systemctl stop firewalld && 
systemctl disable firewalld && 
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && 
iptables -P FORWARD ACCEPT

關閉SELinux:

setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

關閉Swap分割槽:

swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

1.2.6 配置核心引數

注意:所有虛擬機器都需要執行下面的操作

將橋接的IPv4流量傳遞到iptables的鏈,swappiness引數調整:

cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空間,只有當系統 OOM 時才允許使用它
vm.overcommit_memory=1 # 不檢查實體記憶體是否夠用
vm.panic_on_oom=0 # 開啟 OOM
EOF
modprobe ip_vs_rr
modprobe br_netfilter
sysctl --system # 記得回車

2. 安裝Docker

2.1 安裝

Kubernetes從1.6開始使用CRI(Container Runtime Interface)容器執行時介面。預設的容器執行時仍然是Docker,使用的是kubelet中內建dockershim CRI實現。

檢視版本:

# 檢視docker版本
yum list docker-ce.x86_64 --showduplicates | sort -r

# 檢視docker cli版本
yum list docker-ce-cli.x86_64  --showduplicates |sort -r

Kubernetes 1.15已經針對Docker的1.13.1, 17.03, 17.06, 17.09, 18.06,18.09等版本做了驗證,需要注意Kubernetes 1.15最低支援的Docker版本是1.13.1。 我們這裡在各節點安裝docker的19.03.9版本。

# 安裝docker、docker-cli
yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7

# 開機啟動 && 啟動docker
systemctl enable docker && systemctl start docker

# 檢視版本
docker --version

安裝docker還可以通過指令碼,詳情見:https://leisure.wang/procedural-framework/docker/112.html

2.2 配置映象加速

# 第一步:建立目錄(不存在則建立)
mkdir -p /etc/docker

# 第二步:建立並配置daemon.json檔案
cat > /etc/docker/daemon.json <<EOF
{
   "registry-mirrors": [
      "https://registry.docker-cn.com",
      "https://hub-mirror.c.163.com", 
      "https://docker.mirrors.ustc.edu.cn"
   ],
   "exec-opts": ["native.cgroupdriver=systemd"],
   "log-driver": "json-file",
   "log-opts": {
      "max-size": "100m",
      "max-file": "5"
   }
}
EOF

# 第三步:重新載入配置並重啟docker
systemctl daemon-reload && systemctl restart docker

確認一下iptables filter表中FOWARD鏈的預設策略(pllicy)為ACCEPT:

# 命令
iptables -nvL

# 結果部分如下:
Chain INPUT (policy ACCEPT 321 packets, 18442 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0 

3. 使用kubeadm部署k8s叢集

3.1 安裝kubeadm、kubelet、kubectl

需要在每臺機器上都安裝以下的軟體包:

  • Kubelet:負責與其他節點叢集通訊,並進行本節點Pod和容器生命週期的管理。
  • Kubeadm:是Kubernetes的自動化部署工具,降低了部署難度,提高效率。
  • Kubectl:是Kubernetes叢集管理工具。

檢視可用版本:

yum list --showduplicates | grep 'kubeadm\|kubectl\|kubelet'

選擇安裝kubeadm1.18.0、kubelet1.18.0、kubectl1.18.0

# 安裝
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 --disableexcludes=kubernetes

# 此時還不能啟動kubelet,先設定開機啟動
systemctl enable --now kubelet

從安裝結果可以看出還安裝了cri-tools, kubernetes-cni, socat三個依賴:

  • socat是kubelet的依賴
  • cri-tools是CRI(Container Runtime Interface)容器執行時介面的命令列工具

執行kubelet –help可以看到原來kubelet的絕大多數命令列flag引數都被DEPRECATED了。

而官方推薦我們使用–config指定配置檔案,並在配置檔案中指定原來這些flag所配置的內容。具體內容可以檢視這裡Set Kubelet parameters via a config file。這也是Kubernetes為了支援動態Kubelet配置(Dynamic Kubelet Configuration)才這麼做的,參考Reconfigure a Node’s Kubelet in a Live Cluster

kubelet的配置檔案必須是json或yaml格式,具體可檢視這裡

3.2 配置kubeadm

檢視kubelet安裝了哪些檔案:

# 命令
rpm -ql kubelet

# 結果
/etc/kubernetes/manifests				# 清單目錄
/etc/sysconfig/kubelet					# 配置檔案
/usr/bin/kubelet						# 主程式
/usr/lib/systemd/system/kubelet.service	# unit file

在所有虛擬機器上修改/etc/sysconfig/kubelet,加入:

# 命令
sed -i "s/KUBELET_EXTRA_ARGS=/KUBELET_EXTRA_ARGS=\"--fail-swap-on=false\"/" /etc/sysconfig/kubelet

# 檢視是否修改
cat /etc/sysconfig/kubelet

# 檢視結果
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

安裝 kubernetes 主要是安裝它的各個映象,而 kubeadm 已經為我們整合好了執行 kubernetes 所需的基本映象。但由於國內的網路原因,在搭建環境時,無法拉取到這些映象。此時我們只需要修改為阿里雲提供的映象服務即可解決該問題。

匯出配置檔案(未修改檔案,不可用):

kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

針對kubeadm.yml檔案做修改,新增修改處有4個,如下注釋位置,做相應修改即可:

apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.199.231 # 修改項,更改為master節點IP
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: master
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "" # 新增項
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers # 修改項,修改為阿里雲映象倉庫
kind: ClusterConfiguration
kubernetesVersion: v1.18.0
networking:
  dnsDomain: cluster.local
  podSubnet: "10.244.0.0/16" # 新增項,配置Flannel的預設網段
  serviceSubnet: 10.96.0.0/12
scheduler: {}
---
# 新增項start:開啟IPVS模式
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
  SupportIPVSProxyMode: true
mode: ipvs
# 新增項end:開啟IPVS模式

配置修改好後,將配置檔案複製到node1、node2備用:

scp kubeadm.yml root@node1:/root
scp kubeadm.yml root@node2:/root

檢視和拉取映象:

# 檢視所需映象列表
kubeadm config images list --config kubeadm.yml
# 拉取映象 (所有機器都執行)
kubeadm config images pull --config kubeadm.yml
# 執行完畢後,通過命令就可以看到映象了:
docker images

3.3 使用kubeadm 配置master 節點

注意:在master執行下面的操作

3.3.1 安裝 kubernetes 主節點

執行以下命令初始化主節點,該命令指定了初始化時需要使用的配置檔案,其中新增 --experimental-upload-certs 引數可以在後續執行加入節點時自動分發證書檔案。追加的 tee kubeadm-init.log 用以輸出日誌。

# 初始化命令
kubeadm init --config=kubeadm.yml --upload-certs | tee kubeadm-init.log

# 成功則返回如下資訊:
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

node1、node2想要加入叢集,需要執行上一步返回結果中的命令:

kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

--token:加入叢集的token

--discovery-token-ca-cert-hash:發現token證書hash

此時還無法通過命令kubectl get nodes檢視節點資訊,需要等下面的配置。

如果忘記了加入叢集的命令怎麼辦呢?通過下面兩個方法獲取token和discovery-token-ca-cert-hash,然後按照上面的命令的格式拼接起來即可。

獲取Token,可以在 Master 上輸入以下命令檢視:

 kubeadm token list

預設情況下 Token 過期是時間是24小時,如果 Token 過期以後,可以輸入以下命令,生成新的 Token:

kubeadm token create

獲取discovery-token-ca-cert-hash 的方法,在 Master 執行以下命令檢視:

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

注意:如果安裝 kubernetes 版本和下載的映象版本不統一則會出現 timed out waiting for the condition 錯誤。中途失敗或是想修改配置可以使用 kubeadm reset 命令重置配置,再做初始化操作即可。

3.3.2 配置 kubectl

執行初始化叢集時候輸出結果中的命令:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 非root使用者執行
sudo chown $(id -u):$(id -g) $HOME/.kube/config

驗證是否成功:

# 命令
kubectl get nodes

# 結果
NAME     STATUS     ROLES    AGE   VERSION
master   NotReady   master   18m   v1.18.0
node1    NotReady   <none>   14m   v1.18.0
node2    NotReady   <none>   14m   v1.18.0

至此主機誒單配置完成。

3.3.3 kubeadm init執行過程

  • init:指定版本進行初始化操作
  • preflight:初始化前的檢查和下載所需要的 Docker 映象檔案
  • kubelet-start:生成 kubelet 的配置檔案 var/lib/kubelet/config.yaml,沒有這個檔案 kubelet 無法啟動,所以初始化之前的 kubelet 實際上啟動不會成功
  • certificates:生成 Kubernetes 使用的證書,存放在 /etc/kubernetes/pki 目錄中
  • kubeconfig:生成 KubeConfig 檔案,存放在 /etc/kubernetes 目錄中,元件之間通訊需要使用對應檔案
  • control-plane:使用 /etc/kubernetes/manifest 目錄下的 YAML 檔案,安裝 Master 元件
  • etcd:使用 /etc/kubernetes/manifest/etcd.yaml 安裝 Etcd 服務
  • wait-control-plane:等待 control-plan 部署的 Master 元件啟動
  • apiclient:檢查 Master 元件服務狀態。
  • uploadconfig:更新配置
  • kubelet:使用 configMap 配置 kubelet
  • patchnode:更新 CNI 資訊到 Node 上,通過註釋的方式記錄
  • mark-control-plane:為當前節點打標籤,打了角色 Master,和不可排程標籤,這樣預設就不會使用 Master 節點來執行 Pod
  • bootstrap-token:生成 token 記錄下來,後邊使用 kubeadm join 往叢集中新增節點時會用到
  • addons:安裝附加元件 CoreDNS 和 kube-proxy

3.4 使用kubeadm配置 worker 節點

3.4.1 將worker加入到叢集

將 worker節點加入到叢集中很簡單,上一步也做了介紹,只需要執行init返回結果中的命令:

kubeadm join 192.168.199.231:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:d65d8f7646c8503c40d622e29ff4ec74ce3aac5b83f87d2950d2301d6a1faf5c

3.4.2 驗證是否成功

在master節點上執行:

# 命令
kubectl get cs,nodes

# 結果
NAME                                 STATUS    MESSAGE             ERROR
componentstatus/scheduler            Healthy   ok                  
componentstatus/controller-manager   Healthy   ok                  
componentstatus/etcd-0               Healthy   {"health":"true"}   

NAME          STATUS     ROLES    AGE   VERSION
node/master   NotReady   master   84m   v1.18.0
node/node1    NotReady   <none>   80m   v1.18.0
node/node2    NotReady   <none>   79m   v1.18.0

如果 worker節點加入 master 時配置有問題可以在 worker節點上使用 kubeadm reset 重置配置再使用 kubeadm join 命令重新加入即可。希望在 master 節點刪除 node ,可以使用 kubeadm delete nodes 刪除。

3.4.3 檢視 pod 狀態

# 在master上執行
kubectl get pod -n kube-system -o wide

# 結果
NAME                             READY   STATUS    RESTARTS   AGE   IP                NODE     NOMINATED NODE   READINESS GATES
coredns-7ff77c879f-k94rw         0/1     Pending   0          86m   <none>            <none>   <none>           <none>
coredns-7ff77c879f-whhdf         0/1     Pending   0          86m   <none>            <none>   <none>           <none>
etcd-master                      1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
kube-apiserver-master            1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
kube-controller-manager-master   1/1     Running   0          86m   192.168.199.231   master   <none>           <none>
kube-proxy-8jvj5                 1/1     Running   1          86m   192.168.199.231   master   <none>           <none>
kube-proxy-hm8cx                 1/1     Running   1          82m   192.168.199.232   node1    <none>           <none>
kube-proxy-psnc9                 1/1     Running   1          82m   192.168.199.233   node2    <none>           <none>
kube-scheduler-master            1/1     Running   0          86m   192.168.199.231   master   <none>           <none>

由此可以看出 coredns 尚未執行,此時我們還需要安裝網路外掛。

3.5 配置網路

Kubernetes 中可選的 CNI 外掛如下:

  • Flannel
  • Calico
  • Canal
  • Weave

3.5.1 安裝flannel網路

# 下載kube-flannel.yml檔案,如果無法下載請在附件中獲取。
curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 安裝
kubectl apply -f  kube-flannel.yml

3.5.2 配置網路卡名稱(可選)

如果Node有多個網路卡的話,參考flannel issues 39701,目前需要在kube-flannel.yml中使用–iface引數指定叢集主機內網網路卡的名稱,否則可能會出現dns無法解析。需要將kube-flannel.yml下載到本地,flanneld啟動引數加上–iface=,網路卡名稱可通過ip address命令獲取,格式為ensXX

# 部分內容
......
containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.11.0-amd64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        - --iface=ens32
......

3.5.3 檢視Pod狀態

使用kubectl get pod –all-namespaces -o wide確保所有的Pod都處於Running狀態:

# 命令
watch kubectl get pod --all-namespaces -o wide
# 結果(需要等待所有狀態為Running,時間可能需要3-5分鐘)
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE    IP                NODE     NOMINATED NODE   READINESS GATES
kube-system   coredns-7ff77c879f-k94rw         1/1     Running   0          126m   10.244.0.3        master   <none>           <none>
kube-system   coredns-7ff77c879f-whhdf         1/1     Running   0          126m   10.244.0.2        master   <none>           <none>
kube-system   etcd-master                      1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
kube-system   kube-apiserver-master            1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
kube-system   kube-controller-manager-master   1/1     Running   0          126m   192.168.199.231   master   <none>           <none>
kube-system   kube-flannel-ds-amd64-6rcjk      1/1     Running   0          15m    192.168.199.231   master   <none>           <none>
kube-system   kube-flannel-ds-amd64-n464m      1/1     Running   0          15m    192.168.199.232   node1    <none>           <none>
kube-system   kube-flannel-ds-amd64-rlghv      1/1     Running   0          15m    192.168.199.233   node2    <none>           <none>
kube-system   kube-proxy-8jvj5                 1/1     Running   1          126m   192.168.199.231   master   <none>           <none>
kube-system   kube-proxy-hm8cx                 1/1     Running   1          122m   192.168.199.232   node1    <none>           <none>
kube-system   kube-proxy-psnc9                 1/1     Running   1          121m   192.168.199.233   node2    <none>           <none>
kube-system   kube-scheduler-master            1/1     Running   0          126m   192.168.199.231   master   <none>           <none>

至此基本環節已經部署完畢,如果沒有問題,就可以展開k8s的學習之旅了。

3.5.4 問題處理(可選)

3.5.4.1 解決 ImagePullBackOff

在使用 watch kubectl get pods --all-namespaces 命令觀察 Pods 狀態時如果出現 ImagePullBackOff 無法 Running 的情況,請嘗試使用如下步驟處理:

  • Master 中刪除 Nodes:kubectl delete nodes
  • worker中重置配置:kubeadm reset
  • worker重啟計算機:reboot
  • worker重新加入叢集:kubeadm join
3.5.4.2 Master節點參與工作負載

出於安全原因,您的群集不會在主伺服器上安排pod。如果您希望能夠在主伺服器上安排pod,例如對於用於開發的單機Kubernetes叢集,可以執行以下命令:

# 所有主伺服器都安排 pod
kubectl taint nodes --all node-role.kubernetes.io/master-

# 指定節點 master 伺服器都安排 pod
kubectl taint nodes <master-hostname> node-role.kubernetes.io/master-
如:kubectl taint nodes master node-role.kubernetes.io/master-

3.6 驗證叢集DNS是否可用

3.6.1 新建檔案my-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

3.6.2 建立Deployment並生成my-nginx服務

# 建立Deployment
kubectl create -f my-nginx.yaml

# 檢視Deployment
kubectl get deploy

# 生成服務
kubectl expose deploy my-nginx

# 檢視服務
kubectl get services(或 kubectl get svc)
# 結果
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   3h2m
my-nginx     ClusterIP   10.110.206.225   <none>        80/TCP    7m34s

3.6.3 建立dnsutils-ds.yml檔案

建立另一個 Pod,檢視 /etc/resolv.conf 是否包含 kubelet 配置的 --cluster-dns 和 --cluster-domain,是否能夠將服務 my-nginx 解析到對應的 Cluster IP 10.110.206.225

apiVersion: v1
kind: Service
metadata:
  name: dnsutils-ds
  labels:
    app: dnsutils-ds
spec:
  type: NodePort
  selector:
    app: dnsutils-ds
  ports:
  - name: http
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: dnsutils-ds
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  selector:
    matchLabels:
      app: dnsutils-ds
  template:
    metadata:
      labels:
        app: dnsutils-ds
    spec:
      containers:
      - name: my-dnsutils
        image: tutum/dnsutils:latest
        command:
          - sleep
          - "3600"
        ports:
        - containerPort: 80

3.6.4 建立pod dnsutils-ds

kubectl create -f dnsutils-ds.yml

3.6.5 檢視pod節點

# 命令
kubectl get pods

# 結果
NAME                        READY   STATUS             RESTARTS   AGE
curl                        0/1     CrashLoopBackOff   13         46m
dnsutils-ds-2xgtq           1/1     Running            0          103s
dnsutils-ds-dvzjm           1/1     Running            0          103s
dnsutils-ds-xtsvz           1/1     Running            0          103s
my-nginx-5c7d476867-sqpjv   1/1     Running            0          19m
my-nginx-5c7d476867-vv57z   1/1     Running            0          19m

3.6.6 開始驗證DNS

# 命令
kubectl exec dnsutils-ds-2xgtq -- nslookup my-nginx

# 結果
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   my-nginx.default.svc.cluster.local
Address: 10.110.206.225

從結果看Address: 10.110.206.225已經成功了。

另外,解析外部域名時,需要以 . 結尾:

# 命令
kubectl exec dnsutils-ds-2xgtq -- nslookup leisure.wang.

# 結果
Server:         10.96.0.10
Address:        10.96.0.10#53

Non-authoritative answer:
Name:   leisure.wang
Address: 121.36.158.21

3.7 從叢集中刪除Node

如果需要從叢集中移除node2這個Node執行下面的命令:

在master節點上執行:

kubectl drain node2 --delete-local-data --force --ignore-daemonsets
kubectl delete node node2

在 Node 被刪除,需要重啟所有 kubeadm 安裝狀態:

kubeadm reset
# 如果要完全刪除,請執行下面的清理命令
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/

3.8 解決apiserver訪問時匿名使用者禁用問題

瀏覽器訪問 kube-apiserver 的安全埠 6443 時,提示:

{
	"kind": "Status",
	"apiVersion": "v1",
	"metadata": {

	},
	"status": "Failure",
	"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
	"reason": "Forbidden",
	"details": {

	},
	"code": 403
}

對於正式環境,需要建立一個使用者並授權,在上面二進位制二進位制安裝裡介紹過,多少還是煩了點。

對於學習環境,我們不需要那麼麻煩,不就是匿名使用者被禁用了嗎,直接給匿名使用者授權就可以了。

解決辦法:繫結一個cluster-admin的許可權

kubectl create clusterrolebinding system:anonymous   --clusterrole=cluster-admin   --user=system:anonymous

4. 部署whoami

whoami 是一個簡單的HTTP docker服務,用於列印容器ID

在 Master 執行部署 Whoami:

kubectl create deployment whoami --image=idoall/whoami

檢視 Whoami 部署狀態:

kubectl get deployments

檢視 Whoami 的部署資訊:

kubectl describe deployment whoami

檢視 Whoami 的pod資訊:

kubectl describe pod whoami

為 Whoami 擴充套件埠;建立一個可以通過網際網路訪問的 Whoami 容器:

kubectl create service nodeport whoami --tcp=80:80

[本文由https://leisure.wang/整理提供]

上面的命令將在主機上為 Whoami 部署建立面向公眾的服務。
由於這是一個節點埠部署,因此 kubernetes 會將此服務分配給32000+範圍內的主機上的埠。

檢視當前的服務狀態:

# 命令
kubectl get svc,pods -o wide

# 結果
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE     SELECTOR
service/dnsutils-ds   NodePort    10.97.94.13      <none>        80:30157/TCP   37m     app=dnsutils-ds
service/kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP        3h45m   <none>
service/my-nginx      ClusterIP   10.110.206.225   <none>        80/TCP         51m     app=my-nginx
service/whoami        NodePort    10.108.27.255    <none>        80:32729/TCP   29s     app=whoami

NAME                            READY   STATUS             RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
pod/curl                        0/1     CrashLoopBackOff   20         82m     10.244.1.2   node1    <none>           <none>
pod/dnsutils-ds-2xgtq           1/1     Running            0          37m     10.244.1.4   node1    <none>           <none>
pod/dnsutils-ds-dvzjm           1/1     Running            0          37m     10.244.0.4   master   <none>           <none>
pod/dnsutils-ds-xtsvz           1/1     Running            0          37m     10.244.2.3   node2    <none>           <none>
pod/my-nginx-5c7d476867-sqpjv   1/1     Running            0          55m     10.244.1.3   node1    <none>           <none>
pod/my-nginx-5c7d476867-vv57z   1/1     Running            0          55m     10.244.2.2   node2    <none>           <none>
pod/whoami-7976c8ddf6-9lbcp     1/1     Running            0          5m13s   10.244.2.4   node2    <none>           <none>

上面的服務可以看到 Whoami 執行在 32729 埠。

測試 Whoami 服務是否執行正常:

# 命令
curl node1:32729 

# 結果
[mshk.top]I'm whoami-7976c8ddf6-9lbcp

擴充套件部署應用:

kubectl scale --replicas=3 deployment/whoami

檢視擴充套件後的結果,可以看到 Whoami 在 master、node1、node2上面都有部署

ClusterIP 模式會提供一個叢集內部的虛擬IP(與Pod不在同一網段),以供叢集內部的 Pod 之間通訊使用。

刪除 Whoami 部署:

kubectl delete deployment whoami
kubectl delete service whoami

5. 部署Dashboard

Kubernetes Dashboard 是 Kubernetes 叢集的 Web UI,用於管理叢集。

5.1 安裝

注:在master節點上進行如下操作

5.1.0 下載配置檔案

由於網路原因,可能無法下載,無法下載則請直接使用5.1.1檔案內容

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

如果下載成功,請參照5.1.1做如下修改:

  1. 修改映象地址為阿里雲
  2. 修改型別為 NodePort 訪問(無type則新增)
  3. 設定埠號為 30001

5.1.1 建立檔案kubernetes-dashboard.yaml

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kube-system
type: Opaque
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create"]
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  verbs: ["get", "update", "delete"]
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["kubernetes-dashboard-settings"]
  verbs: ["get", "update"]
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
      - name: kubernetes-dashboard
        image: registry.aliyuncs.com/google_containers/kubernetes-dashboard-amd64:v1.10.1 # 修改映象地址為阿里雲
        ports:
        - containerPort: 8443
          protocol: TCP
        args:
          - --auto-generate-certificates
        volumeMounts:
        - name: kubernetes-dashboard-certs
          mountPath: /certs
        - mountPath: /tmp
          name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTPS
            path: /
            port: 8443
          initialDelaySeconds: 30
          timeoutSeconds: 30
      volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort # 修改型別為 NodePort 訪問(無type則新增)
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001 # 設定埠號為 30001
  selector:
    k8s-app: kubernetes-dashboard

5.1.2 部署

kubectl create -f kubernetes-dashboard.yaml

5.1.3 檢視

kubectl -n kube-system get pods
kubectl -n kube-system get service kubernetes-dashboard
kubectl -n kube-system describe service kubernetes-dashboard

5.2 訪問

需要使用 NodeIP:30001(如:https://192.168.199.231:30001/) 訪問 Dashboard,因為證書原因除火狐瀏覽器外其它瀏覽器無法直接開啟頁面。

作為學習,暫時可以不用在意這些細節。訪問後,在火狐裡點選高階>接受風險並繼續。

此時將會看到“Kubernetes 儀表板”。

5.3 登入

5.3.1 kubeconfig方式

該config檔案位置一般是 ~/.kube/config(Master節點),只要將該檔案下載到本地機器上,登入的時候選擇它就行了。

5.3.2 令牌方式

建立訪問Dashboard的token,需要建立一個 Admin 使用者並授予 Admin 角色繫結,使用下面的 yaml檔案 建立 admin 使用者並賦予管理員許可權,然後可以通過 Token 訪問 kubernetes。

建立 kubernetes-dashboard-admin.yaml 檔案:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

執行部署:

kubectl apply -f kubernetes-dashboard-admin.yaml

獲取secret中的token值:

kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token
# 記得替換成你自己的secret資源名 
kubectl -n kube-system describe secret kubernetes-dashboard-token-bsjtr

也可以通過 jsonpath 直接獲取 token:

kubectl -n kube-system get secret kubernetes-dashboard-token-bsjtr -o jsonpath={.data.token}|base64 -d

也可以使用下面的命令,直接獲取 kubernetes-dashboard-token 的值,然後直接列印輸出:

k8tokenvalue=`kubectl get secret -o wide --all-namespaces | grep kubernetes-dashboard-token | awk '{print $2}'`;kubectl -n kube-system get secret $k8tokenvalue -o jsonpath={.data.token}|base64 -d | awk '{print $1}'

注意:下面的獲取token值的方式和上面三種方式選擇一種即可。

您還可以通過kubectl create clusterrolebinding的方式來授予 Dashboard 服務 Admin 管理員許可權:

kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

登入成功後就能看到後臺頁面了:

6. Weave Scope 監控叢集

建立 Kubernetes 叢集並部署容器化應用只是第一步。一旦叢集執行起來,我們需要確保一起正常,所有必要元件就位並各司其職,有足夠的資源滿足應用的需求。Kubernetes 是一個複雜系統,運維團隊需要有一套工具幫助他們獲知叢集的實時狀態,併為故障排查提供及時和準確的資料支援。

6.1 安裝

Weave Scope 是 Docker 和 Kubernetes 視覺化監控工具。Scope 提供了至上而下的叢集基礎設施和應用的完整檢視,使用者可以輕鬆對分散式的容器化應用進行實時監控和問題診斷。

在 K8s 叢集中安裝 Scope 的方法很簡單,使用下面的命令:

# 命令
kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '\n')&k8s-service-type=NodePort"

# 結果
service-type=NodePort"
namespace/weave created
serviceaccount/weave-scope created
clusterrole.rbac.authorization.k8s.io/weave-scope created
clusterrolebinding.rbac.authorization.k8s.io/weave-scope created
deployment.apps/weave-scope-app created
service/weave-scope-app created
deployment.apps/weave-scope-cluster-agent created
daemonset.apps/weave-scope-agent created

部署成功後有如下元件:

# 命令
kubectl get pod -n weave
# 結果
NAME                                         READY   STATUS              RESTARTS   AGE
weave-scope-agent-2t7z2                      0/1     ContainerCreating   0          60s
weave-scope-agent-ll9r9                      0/1     ContainerCreating   0          60s
weave-scope-agent-qzp2b                      0/1     ContainerCreating   0          60s
weave-scope-app-bc7444d59-lznk8              0/1     ContainerCreating   0          62s
weave-scope-cluster-agent-7944c858c9-ms7mz   0/1     ContainerCreating   0          61s

# 命令
kubectl get svc -n weave
# 結果
NAME              TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
weave-scope-app   NodePort   10.108.61.84   <none>        80:30286/TCP   3m9s

# 命令
kubectl get deploy -n weave
# 結果
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
weave-scope-app             1/1     1            1           4m19s
weave-scope-cluster-agent   1/1     1            1           4m18s
  • DaemonSet weave-scope-agent,叢集每個節點上都會執行的 scope agent 程式,負責收集資料。
  • Deployment weave-scope-app,scope 應用,從 agent 獲取資料,通過 Web UI 展示並與使用者互動。
  • Service weave-scope-app,預設是 ClusterIP 型別,我們已經在上面的命令中新增了引數k8s-service-type=NodePort修改為 NodePort。

6.2 使用Scope

瀏覽器訪問http://MASTER_IP:30286/(埠可在上一步檢視命令中獲得),cope 預設顯示當前所有的 Controller(Deployment、DaemonSet 等)。

6.2.1 拓撲結構

Scope 會自動構建應用和叢集的邏輯拓撲。比如點選頂部 Pods,會顯示所有 Pod 以及 Pod 之間的依賴關係。

點選 Hosts,會顯示各個節點之間的關係,可以在 Scope 中檢視資源的 CPU 和記憶體使用情況。

6.2.2 線上操作

Scope 還提供了便捷的線上操作功能,比如選中某個 Host,點選 >_ 按鈕可以直接在瀏覽器中開啟節點的命令列終端:

點選 Deployment 的 + 可以執行 Scale Up 操作:

可以檢視 Pod 的日誌:

可以 attach、restart、stop 容器,以及直接在 Scope 中排查問題:

6.2.3 強大的搜尋功能

Scope 支援關鍵字搜尋和定位資源。

還可以進行條件搜尋,比如查詢和定位 MEMORY > 1M 的 Containers。

Weave Scope 介面極其友好,操作簡潔流暢,更多功能留給大家去探索。

官方文件:https://www.weave.works/docs/scope/latest/installing/#k8s

寫在最後

通過kubeadm安裝k8s叢集環境的介紹就到這裡了,書寫安裝過程難免出現不足的地方,如果出了問題,需要讀者多多思考。由於國內網路的原因,文件中所需要的大部分配置檔案都已經貼了出來,讀者只需要根據自己的機器環境做相應的修改即可。通過kubeadm安裝k8s叢集環境,相對於二進位制的安裝方式來說,還是比較簡單的,需要多多實踐,才能出真知。我是東方雨傾,感謝大家的支援,謝謝!

附件

連結:https://pan.baidu.com/s/1qWdZ_CclTxm2ybE4h8dziA
提取碼:ruo5

原文地址:https://leisure.wang/procedural-framework/docker/513.html

相關文章