kubernetes之1---yum部署K8S集群


k8s集群yum安裝

目錄

k8s集群架構

核心組件:

1563068809299


Add-ons:

組件名稱 說明
kube-dns 負責為整個集群提供DNS服務
Ingress Controller 為服務提供外網入口
Heapster 提供資源監控
Dashboard 提供GUI
Federation 提供跨可用區的集群
Fluentd-elasticsearch 提供集群日志采集、存儲與查詢

環境准備

主機名 IP 配置
k8s-master 10.0.0.11 1核1G
k8s-node-1 10.0.0.12 1核1G
k8s-node-2 10.0.0.13 1核1G
  • 關閉:selinuxfirewalldNetworkManagerpostfix(非必須)

  • 修改IP地址、主機名

hostnamectl set-hostname 主機名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
  • 添加hosts解析
cat >> /etc/hosts <<EOF
10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
10.0.0.14 k8s-node-3
EOF

master部署

etcd

  1. 安裝
yum install etcd -y
  1. 配置
sed -i "6c ETCD_LISTEN_CLIENT_URLS=\"http://0.0.0.0:2379\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.11:2379\"" /etc/etcd/etcd.conf
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/default.etcd" # 數據文件存放路徑
#ETCD_WAL_DIR=""
#ETCD_LISTEN_PEER_URLS="http://localhost:2380" # 同類監聽地址,用於集群時同步
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379" # 客戶端監聽地址
#ETCD_MAX_SNAPSHOTS="5"  # 快照最大數量
#ETCD_MAX_WALS="5"
ETCD_NAME="default"      # 服務名,集群時不能一樣
... ...
#
#[Clustering]
#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
... ...
  1. 啟動並加入開機啟動
systemctl start etcd.service
systemctl enable etcd.service
  1. 檢查集群健康狀態
etcdctl -C http://10.0.0.11:2379 cluster-health

要加入已有集群,先在集群再添加成員,再在成員節點修改配置文件status="existing",啟動服務。

etcdctl member list
etcdctl member remove 成員
etcdctl member add nodeN URL
  1. etcdctl命令介紹
etcdctl [global options] command [command options] [arguments...]

etcdctl mk [command options] <key> <value>
etcdctl ls [command options] [key]
etcdctl set [command options] <key> <value>
etcdctl get [command options] <key>

backup          # 備份etcd目錄
cluster-health  # 檢查etcd群集的運行狀況
mk              # 生成一個具有給定值的新鍵
mkdir           # 創建新目錄
rm              # 刪除鍵或目錄
rmdir           # 刪除鍵。如果是空目錄或鍵值對
get             # 檢索鍵的值
ls              # 檢索目錄
set             # 設置鍵的值
setdir          # 創建新目錄或更新現有目錄TTL
update          # 使用給定值更新現有密鑰
updatedir       # 更新現有目錄
watch           # 觀察鍵的變化
exec-watch      # 觀察一個鍵的變化並執行一個可執行文件
member          # 成員add、remove和list子命令
user            # 用戶add、grant和revoke子命令
role            # 角色add、grant和revoke子命令
auth            # 總體身份驗證控制

kubernetes-master

  1. 安裝
yum install kubernetes-master -y
  1. 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver

默認配置文件:

###
# kubernetes system config
#
# The following values are used to configure the kube-apiserver
#

# The address on the local server to listen to.
KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1"

# The port on the local server to listen on.
# KUBE_API_PORT="--port=8080"

# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"

# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"

# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

# Add your own!
KUBE_API_ARGS=""
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config

默認配置文件:

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://127.0.0.1:8080"
  1. 啟動並加入開機啟動
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl start kube-scheduler.service
  1. 檢查服務是否安裝正常
[root@k8s-master ~]# kubectl get componentstatus
NAME                 STATUS    MESSAGE             ERROR
etcd-0               Healthy   {"health":"true"}   
scheduler            Healthy   ok                  
controller-manager   Healthy   ok

node部署

kubernetes-node(集成cadvisor)

  1. 安裝
yum install kubernetes-node -y
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config
  1. 配置kubelet
sed -i "5c KUBELET_ADDRESS=\"--address=0.0.0.0\"" /etc/kubernetes/kubelet
sed -i "8c KUBELET_PORT=\"--port=10250\"" /etc/kubernetes/kubelet
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.11:8080\"" /etc/kubernetes/kubelet

k8s-node-1:10.0.0.12

sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.12\"" /etc/kubernetes/kubelet

k8s-node-2:10.0.0.13

sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.13\"" /etc/kubernetes/kubelet

默認配置文件:

###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=127.0.0.1"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=127.0.0.1"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://127.0.0.1:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrast
ructure:latest"

# Add your own!
KUBELET_ARGS=""
  1. 啟動並加入開機啟動
systemctl enable docker
systemctl enable kubelet.service
systemctl enable kube-proxy.service
systemctl start kubelet.service
systemctl start kube-proxy.service
  1. 在master節點檢查
kubectl get nodes
  1. 訪問cadvisor的web界面:

所有節點配置flannel網絡

  1. 安裝
yum install flannel -y
  1. 配置
sed -i 's#127.0.0.1#10.0.0.11#g' /etc/sysconfig/flanneld
  1. master節點創建key,安裝docker啟動並加入開機啟動
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'

flannel三種模式:

  • udp:性能最差
  • vxlan:性能較好
  • host-gw:性能最好,但雲主機不能用
yum install docker -y
systemctl enable docker
systemctl start docker
  1. 啟動並加入開機啟動
systemctl enable flanneld.service
systemctl start flanneld.service

docker指定bip設置docker0網卡的IP

  1. 配置docker服務啟動文件:啟動時設置iptables規則允許轉發
sed -i "/ExecStart=/i ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT" /usr/lib/systemd/system/docker.service
systemctl daemon-reload
systemctl restart docker
  1. 查看flannel網卡
ifconfig flannel0
  1. 驗證各節點互通
docker run -it alpine
ifconfig
  1. 配置倉庫信任和加速
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["10.0.0.11:5000"]
}
EOF
systemctl restart docker

master部署鏡像倉庫

docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry

node提交鏡像測試

docker tag alpine:3.9 10.0.0.11:5000/alpine:3.9
docker push 10.0.0.11:5000/alpine:3.9

查看倉庫鏡像文件

ls /opt/myregistry/docker/registry/v2/repositories

k8s介紹

k8s是一個docker集群的管理工具,是容器的編排工具。

Kubernetes 是用於自動部署,擴展和管理容器化應用程序的開源系統。

Kubernetes 源自Google 15 年生產環境的運維經驗(使用golang重構borg(容器管理平台) -->kubernetes),同時凝聚了社區的最佳創意和實踐。

Kubernetes官方文檔 中文社區

k8s歷史:

  • 2014年 docker容器編排工具,立項

  • 2015年7月 發布kubernetes 1.0,加入cncf基金會,孵化

  • 2016年 kubernetes 1.2干掉兩個對手,docker swarm,mesos marathon

  • 2017年 1.5-1.9

  • 2018年 k8s 從cncf基金會畢業,1.10 1.11 1.12

  • 2019年:1.13,1.14,1.15,1.16,1.17

  • 2020年:1.18,1.19,1.20

cncf:Cloud Native Compute Foundation 孵化器

kubernetes (k8s):希臘語 舵手,領航者 容器編排領域,


k8s核心功能

自我修復: 重新啟動失敗的容器,在節點不可用時,替換和重新調度節點上的容器,對用戶定義的健康檢查不響應的容器會被中止,並且在容器准備好服務之前不會把其向客戶端廣播。

彈性伸縮: 通過監控容器的cpu的負載值,如果這個平均高於80%,增加容器的數量;如果這個平均低於10%,減少容器的數量。

服務的自動發現和負載均衡:不需要修改您的應用程序來使用不熟悉的服務發現機制,Kubernetes 為容器提供了自己的 IP 地址和一組容器的單個 DNS 名稱,並可以在它們之間進行負載均衡。

滾動升級和一鍵回滾: Kubernetes 逐漸部署對應用程序或其配置的更改,同時監視應用程序運行狀況,以確保它不會同時終止所有實例。 如果出現問題,Kubernetes會為您恢復更改,利用日益增長的部署解決方案的生態系統。

私密配置文件管理:web容器里,數據庫的賬戶密碼(測試庫密碼)


k8s安裝方式

  • yum安裝:1.5.2;最容易安裝成功,最適合學習的

  • 源碼編譯安裝:難度最大,可以安裝最新版

  • 二進制安裝:步驟繁瑣,可以安裝最新版,自動化腳本(shell,ansible,saltstack),適合生產

  • kubeadm:安裝最容易,可以安裝最新版,國外網絡,適合生產

  • minikube:適合開發人員體驗k8s, 國外網絡


k8s應用場景

k8s最適合跑微服務項目!


k8s開機檢查

kubectl get componentstatus
kubectl get nodes
kubectl get pod -o wide
[root@k8s-master ~]# kubectl get componentstatus # 檢查組件狀態
NAME                 STATUS    MESSAGE             ERROR
etcd-0               Healthy   {"health":"true"}   
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
[root@k8s-master ~]# kubectl get nodes # 檢查nodes節點狀態
NAME        STATUS    AGE
10.0.0.12   Ready     21m
10.0.0.13   Ready     3d
[root@k8s-master ~]# kubectl get pod -o wide # 檢查pod節點狀態
NAME          READY     STATUS    RESTARTS   AGE       IP             NODE
nginx-8phch   1/1       Running   1          13h       172.18.100.2   10.0.0.13
nginx-dc8wc   1/1       Running   1          13h       172.18.100.3   10.0.0.13
nginx-kcmpv   1/1       Running   1          13h       172.18.100.4   10.0.0.13
nginx-mknrb   1/1       Running   1          13h       172.18.100.6   10.0.0.13
nginx-zk9kg   1/1       Running   0          8s        172.18.68.2    10.0.0.12
[root@k8s-master ~]# ping 172.18.100.2
PING 172.18.100.2 (172.18.100.2) 56(84) bytes of data.
64 bytes from 172.18.100.2: icmp_seq=1 ttl=63 time=3.82 ms
64 bytes from 172.18.100.2: icmp_seq=2 ttl=63 time=0.380 ms
^C
--- 172.18.100.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.380/2.104/3.829/1.725 ms
[root@k8s-master ~]# ping 172.18.68.2
PING 172.18.68.2 (172.18.68.2) 56(84) bytes of data.
64 bytes from 172.18.68.2: icmp_seq=1 ttl=63 time=2.48 ms
64 bytes from 172.18.68.2: icmp_seq=2 ttl=63 time=0.354 ms
^C
--- 172.18.68.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.354/1.421/2.488/1.067 ms

k8s資源

准備:

node下載鏡像,上傳至私有倉庫

docker pull nginx:1.13
docker tag docker.io/nginx:1.13 10.0.0.11:5000/nginx:1.13
docker push 10.0.0.11:5000/nginx:1.13
docker pull nginx:1.15
docker tag docker.io/nginx:1.15 10.0.0.11:5000/nginx:1.15
docker push 10.0.0.11:5000/nginx:1.15
docker pull alpine
docker tag docker.io/alpine:latest 10.0.0.11:5000/alpine:latest
docker push 10.0.0.11:5000/alpine:latest

Pod

Pod(容器組)是 Kubernetes 中最小的調度單元,可以通過 yaml 定義文件直接創建一個 Pod。

Pod 本身並不具備自我恢復(self-healing),彈性伸縮等高級特性。如果一個 Pod 所在的節點出現故障,或者調度程序自身出現問題,以及節點資源不夠或節點進入維護而驅逐 Pod 時,Pod 將被刪除,且不能自我恢復。

啟動一個pod,至少會有兩個容器,基礎容器pause和業務容器,多個業務容器共享一個基礎容器。一個Pod中的容器默認共享網絡命名空間,

Pod容器分類

  • Infrastructure Container:基礎容器pause,維護整個Pod網絡空間。
  • InitContainers:初始化容器,先於業務容器開始執行。
  • Containers:業務容器,並行啟動。

Pod存在的意義:為親密性應用而存在

  • 兩個應用之間發生文件交互
  • 兩個應用需要通過127.0.0.1或socker通信
  • 兩個應用需要發生頻繁的調用

任何一個k8s資源都可以由yml清單文件來定義。

apiVersion: v1       # 版本號
kind: Pod            # Pod
metadata:            # 元數據
  name: string       # Pod名稱
  namespace: string  # Pod所屬的命名空間
  labels:            # 自定義標簽
    - name: string   # 自定義標簽名字
  annotations:       # 自定義注釋列表
    - name: string
spec:                # Pod中容器的詳細定義
  containers:        # Pod中容器列表
  - name: string     # 容器名稱
    image: string    # 容器的鏡像名稱
    imagePullPolicy: [Always | Never | IfNotPresent] # 獲取鏡像的策略 Alawys表示下載鏡像 IfnotPresent表示優先使用本地鏡像,否則下載鏡像,Nerver表示僅使用本地鏡像
    command: [string]  # 容器的啟動命令列表,如不指定,使用打包時使用的啟動命令
    args: [string]     # 容器的啟動命令參數列表
    workingDir: string # 容器的工作目錄
    volumeMounts:      # 掛載到容器內部的存儲卷配置
    - name: string     # 引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名
      mountPath: string    # 存儲卷在容器內mount的絕對路徑,應少於512字符
      readOnly: boolean    # 是否為只讀模式
    ports:             # 需要暴露的端口庫號列表
    - name: string     # 端口號名稱
      containerPort: int   # 容器需要監聽的端口號
      hostPort: int    # 容器所在主機需要監聽的端口號,默認與Container相同
      protocol: string # 端口協議,支持TCP和UDP,默認TCP
    env:               # 容器運行前需設置的環境變量列表
    - name: string     # 環境變量名稱
      value: string    # 環境變量的值
    resources:         # 資源限制和請求的設置
      limits:          # 資源限制的設置
        cpu: string    #Cpu的限制,單位為core數,將用於docker run --cpu-shares參數
        memory: string #內存限制,單位可以為Mib/Gib,將用於docker run --memory參數
      requests:        # 資源請求的設置
        cpu: string    # Cpu請求,容器啟動的初始可用數量
        memory: string # 內存請求,容器啟動的初始可用數量
    livenessProbe:     # 對Pod內個容器健康檢查的設置,當探測無響應幾次后將自動重啟該容器,檢查方法有exec、httpGet和tcpSocket,對一個容器只需設置其中一種方法即可
      exec:          # 對Pod容器內檢查方式設置為exec方式
        command: [string]  # exec方式需要制定的命令或腳本
      httpGet:       # 對Pod內個容器健康檢查方法設置為HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     # 對Pod內個容器健康檢查方式設置為tcpSocket方式
         port: number
       initialDelaySeconds: 0  # 容器啟動完成后首次探測的時間,單位為秒
       timeoutSeconds: 0   # 對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
       periodSeconds: 0    # 對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure] # Pod的重啟策略,Always表示一旦不管以何種方式終止運行,kubelet都將重啟,OnFailure表示只有Pod以非0退出碼退出才重啟,Nerver表示不再重啟該Pod
    nodeSelector: obeject  # 設置NodeSelector表示將該Pod調度到包含這個label的node上,以key:value的格式指定
    imagePullSecrets:      # Pull鏡像時使用的secret名稱,以key:secretkey格式指定
    - name: string
    hostNetwork:false      # 是否使用主機網絡模式,默認為false,如果設置為true,表示使用宿主機網絡
    volumes:           # 在該pod上定義共享存儲卷列表
    - name: string     # 共享存儲卷名稱 (volumes類型有很多種)
      emptyDir: {}     # 類型為emtyDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值
      hostPath: string # 類型為hostPath的存儲卷,表示掛載Pod所在宿主機的目錄
        path: string   # Pod所在宿主機的目錄,將被用於同期中mount的目錄
      secret:          # 類型為secret的存儲卷,掛載集群與定義的secre對象到容器內部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:      # 類型為configMap的存儲卷,掛載預定義的configMap對象到容器內部
        name: string
        items:
        - key: string
          path: string

k8s yaml的主要組成:

  • apiVersion:v1 :api版本
  • kind:pod :資源類型
  • metadata :屬性
  • spec :詳細

  1. master節點編寫pod資源yaml
mkdir -p /root/k8s_yaml/pod && cd /root/k8s_yaml/pod
cat > /root/k8s_yaml/pod/k8s_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
EOF
  1. master節點創建資源
kubectl create -f k8s_pod.yaml
  1. master節點查看所有pod資源狀態(集裝箱化)
[root@k8s-master pod]# kubectl get pod
NAME      READY     STATUS              RESTARTS   AGE
nginx     0/1       ContainerCreating   0          27m
  1. master節點查看指定pod資源描述(調度至10.0.0.13)
[root@k8s-master pod]# kubectl describe pod nginx
Name:		nginx
Namespace:	default
Node:		10.0.0.13/10.0.0.13
Start Time:	Mon, 07 Dec 2020 16:19:46 +0800
Labels:		app=web
Status:		Pending
IP:		
Controllers:	<none>
Containers:
  nginx:
    Container ID:		
    Image:			10.0.0.11:5000/nginx:1.13
    Image ID:			
    Port:			80/TCP
    State:			Waiting
      Reason:			ContainerCreating
    Ready:			False
    Restart Count:		0
    Volume Mounts:		<none>
    Environment Variables:	<none>
Conditions:
  Type		Status
  Initialized 	True 
  Ready 	False 
  PodScheduled 	True 
No volumes.
QoS Class:	BestEffort
Tolerations:	<none>
Events:
  FirstSeen	LastSeen	Count	From			SubObjectPath	Type		Reason		Message
  ---------	--------	-----	----			-------------	--------	------		-------
  27m		27m		1	{default-scheduler }			Normal		Scheduled	Successfully assigned nginx to 10.0.0.13
  27m		1m		10	{kubelet 10.0.0.13}			Warning		FailedSync	Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request.  details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

  27m	39s	116	{kubelet 10.0.0.13}		Warning	FailedSync	Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""

  0s	0s	1	{kubelet 10.0.0.13}		Warning	MissingClusterDNS	kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  1. node節點(10.0.0.13)搜索缺失鏡像並下載,上傳至私有倉庫
docker search pod-infrastructure
docker pull docker.io/tianyebj/pod-infrastructure
docker tag docker.io/tianyebj/pod-infrastructure:latest 10.0.0.11:5000/pod-infrastructure:latest
docker push 10.0.0.11:5000/pod-infrastructure:latest
  1. 所有node節點修改配置文件,指定POD下載鏡像地址為私有倉庫,重啟服務
sed -i "17c KUBELET_POD_INFRA_CONTAINER=\"--pod-infra-container-image=10.0.0.11:5000/pod-infrastructure:latest\"" /etc/kubernetes/kubelet
systemctl restart kubelet.service
  1. master節點再次查看所有pod資源狀態(運行中)
[root@k8s-master pod]# kubectl get pod -o wide  # -o 顯示更寬
NAME      READY     STATUS    RESTARTS   AGE       IP             NODE
nginx     1/1       Running   0          59m       172.18.100.2   10.0.0.13
  1. node節點(10.0.0.13)查看運行的容器
[root@k8s-node-2 ~]# docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS              PORTS               NAMES
f4a6497de298        10.0.0.11:5000/nginx:1.13                  "nginx -g 'daemon ..."   34 minutes ago      Up 34 minutes                           k8s_nginx.91390390_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_362db3ed
8cf407292934        10.0.0.11:5000/pod-infrastructure:latest   "/pod"                   34 minutes ago      Up 34 minutes                           k8s_POD.177f01b0_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_9d56b0b4
[root@k8s-node-2 ~]# docker inspect f4a6497de298 | grep NetworkMode
            "NetworkMode": "container:8cf407292934095b3ddabecb197adb33acda43bc38a7ee73a12a681ca30a9a43",
[root@k8s-node-2 ~]# docker inspect 8cf407292934 | grep -A 1 Networks
            "Networks": {
                "bridge": {

pod資源至少由兩個容器組成:基礎容器pause和(多個)業務容器nginx組成,共用網絡空間。

基礎容器pod用於實現k8s高級功能。

  1. master節點編寫pod資源yaml(兩個業務容器)
cat > /root/k8s_yaml/pod/k8s_pod2.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
    - name: alpine
      image: 10.0.0.11:5000/alpine:latest
      command: ["sleep","1000"]
EOF
  1. master節點創建資源
kubectl create -f k8s_pod2.yaml
  1. master節點查看所有pod資源狀態
[root@k8s-master pod]# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
nginx     1/1       Running   0          2h
test      2/2       Running   1          28m
  1. node節點(10.0.0.12)查看運行的容器(輪詢負載均衡)
[root@k8s-node-1 ~]# docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS              PORTS               NAMES
7bf33f049a9c        10.0.0.11:5000/alpine:latest               "sleep 1000"             11 minutes ago      Up 11 minutes                           k8s_alpine.314fe414_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_48c71571
363f874e9d5a        10.0.0.11:5000/nginx:1.13                  "nginx -g 'daemon ..."   28 minutes ago      Up 28 minutes                           k8s_nginx.91390390_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_f036679b
d75cc74ef792        10.0.0.11:5000/pod-infrastructure:latest   "/pod"                   28 minutes ago      Up 28 minutes                           k8s_POD.177f01b0_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_96282638
[root@k8s-node-1 ~]# docker inspect 7bf33f049a9c | grep NetworkMode
            "NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect 363f874e9d5a | grep NetworkMode
            "NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect d75cc74ef792 | grep -A 1 Networks
            "Networks": {
                "bridge": {

ReplicationController

Replication Controller 副本控制器,應用托管在Kubernetes后,Kubernetes需要保證應用能夠持續運行,這是RC的工作內容,它會確保任何時間Kubernetes中都有指定數量的Pod正在運行。在此基礎上,RC還提供了一些高級的特性,比如滾動升級、升級回滾等。

新版 Kubernetes 建議使用 ReplicaSet(簡稱為RS )來取代 ReplicationController。


  1. master節點編寫ReplicationController資源yaml
mkdir -p /root/k8s_yaml/rc && cd /root/k8s_yaml/rc
cat > /root/k8s_yaml/rc/k8s_rc.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 5  # 副本5個
  selector:
    app: myweb
  template:    # Pod模板
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
EOF
  1. master節點創建資源(5個pod)
kubectl create -f k8s_rc.yaml
  1. master節點查看資源狀態
[root@k8s-master rc]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
nginx     5         5         5         6s
[root@k8s-master rc]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
nginx         1/1       Running   0          2h
nginx-2w6fb   1/1       Running   0          1m
nginx-35m8t   1/1       Running   0          1m
nginx-7xhms   1/1       Running   0          1m
nginx-kxljm   1/1       Running   0          1m
nginx-sv4d5   1/1       Running   0          1m
test          2/2       Running   2          38m

rc保證指定數量的pod始終存活

  1. master節點刪除一個pod,再查看資源狀態:仍然有5個pod
[root@k8s-master rc]# kubectl delete pod nginx-2w6fb
pod "nginx-2w6fb" deleted
[root@k8s-master rc]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
nginx         1/1       Running   0          2h
nginx-35m8t   1/1       Running   0          2m
nginx-5mbbq   1/1       Running   0          4s
nginx-7xhms   1/1       Running   0          2m
nginx-kxljm   1/1       Running   0          2m
nginx-sv4d5   1/1       Running   0          2m
test          2/2       Running   2          38m
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY  STATUS    RESTARTS   AGE   IP             NODE
nginx         1/1    Running   0          2h    172.18.100.2   10.0.0.13
nginx-35m8t   1/1    Running   0          6m    172.18.100.3   10.0.0.13
nginx-5mbbq   1/1    Running   0          4m    172.18.68.5    10.0.0.12
nginx-7xhms   1/1    Running   0          6m    172.18.100.4   10.0.0.13
nginx-kxljm   1/1    Running   0          6m    172.18.68.3    10.0.0.12
nginx-sv4d5   1/1    Running   0          6m    172.18.100.5   10.0.0.13
test          2/2    Running   2          43m   172.18.68.2    10.0.0.12
  1. 關閉一個node節點(10.0.0.12)(等2分鍾)
systemctl stop kubelet.service
  1. master節點查看到一個node節點離線,移除該節點
[root@k8s-master rc]# kubectl get node
NAME        STATUS     AGE
10.0.0.12   NotReady   3d
10.0.0.13   Ready      3d
[root@k8s-master rc]# kubectl delete node 10.0.0.12
node "10.0.0.12" deleted
  1. master節點查看資源狀態(rc資源自動遷移)
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE       IP             NODE
nginx         1/1       Running   0          2h        172.18.100.2   10.0.0.13
nginx-35m8t   1/1       Running   0          10m       172.18.100.3   10.0.0.13
nginx-7xhms   1/1       Running   0          10m       172.18.100.4   10.0.0.13
nginx-dhcxr   1/1       Running   0          7s        172.18.100.7   10.0.0.13
nginx-jqhr9   1/1       Running   0          7s        172.18.100.6   10.0.0.13
nginx-sv4d5   1/1       Running   0          10m       172.18.100.5   10.0.0.13

rc通過標簽選擇器來關聯pod

  1. master節點刪除一個pod
kubectl delete pod nginx-35m8t

使用--all參數刪除所有指定種類資源

kubectl delete pod --all
  1. master節點查看標簽
[root@k8s-master rc]# kubectl get pod --show-labels
NAME          READY     STATUS    RESTARTS   AGE       LABELS
nginx         1/1       Running   0          2h        app=web
nginx-7xhms   1/1       Running   0          14m       app=myweb
nginx-ccxz2   1/1       Running   0          11s       app=myweb
nginx-dhcxr   1/1       Running   0          4m        app=myweb
nginx-jqhr9   1/1       Running   0          4m        app=myweb
nginx-sv4d5   1/1       Running   0          14m       app=myweb
[root@k8s-master rc]# kubectl get rc -o wide
NAME      DESIRED   CURRENT   READY     AGE       CONTAINER(S)   IMAGE(S)                    SELECTOR
nginx     5         5         5         13m       myweb          10.0.0.11:5000/nginx:1.13   app=myweb
  1. 修改nginx的標簽為app: myweb,自動刪除最年輕的pod資源,保持5個
[root@k8s-master rc]# kubectl edit pod nginx
[root@k8s-master rc]# kubectl get pod --show-labels
NAME          READY     STATUS    RESTARTS   AGE       LABELS
nginx         1/1       Running   0          2h        app=myweb
nginx-7xhms   1/1       Running   0          16m       app=myweb
nginx-dhcxr   1/1       Running   0          5m        app=myweb
nginx-jqhr9   1/1       Running   0          5m        app=myweb
nginx-sv4d5   1/1       Running   0          16m       app=myweb

rc滾動升級

  1. 根據k8s_rc2.yaml創建升級k8s_rc2.yaml,修改:
    • name
    • app
    • image

1563093237250

cat > /root/k8s_yaml/rc/k8s_rc2.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx2
spec:
  replicas: 5
  selector:
    app: myweb2
  template:
    metadata:
      labels:
        app: myweb2
    spec:
      containers:
      - name: myweb2
        image: 10.0.0.11:5000/nginx:1.15
        ports:
        - containerPort: 80
EOF
  1. 升級(5s一個)
kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
[root@k8s-master rc]# kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
Created nginx2
Scaling up nginx2 from 0 to 5, scaling down nginx from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx2 up to 1
Scaling nginx down to 4
Scaling nginx2 up to 2
Scaling nginx down to 3
Scaling nginx2 up to 3
Scaling nginx down to 2
Scaling nginx2 up to 4
Scaling nginx down to 1
Scaling nginx2 up to 5
Scaling nginx down to 0
Update succeeded. Deleting nginx
replicationcontroller "nginx" rolling updated to "nginx2"
[root@k8s-master rc]# kubectl get pod -o wide
NAME           READY     STATUS    RESTARTS   AGE  IP             NODE
nginx2-725jx   1/1       Running   0          35s  172.18.100.6   10.0.0.13
nginx2-fhw68   1/1       Running   0          30s  172.18.100.3   10.0.0.13
nginx2-l4b5f   1/1       Running   0          50s  172.18.100.7   10.0.0.13
nginx2-r027f   1/1       Running   0          40s  172.18.100.8   10.0.0.13
nginx2-rkc14   1/1       Running   0          25s  172.18.100.2   10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Mon, 07 Dec 2020 11:26:46 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 02 Oct 2018 14:49:27 GMT
Connection: keep-alive
ETag: "5bb38577-264"
Accept-Ranges: bytes
  1. 回滾(1s一個)
kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
[root@k8s-master rc]# kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
Created nginx
Scaling up nginx from 0 to 5, scaling down nginx2 from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx up to 1
Scaling nginx2 down to 4
Scaling nginx up to 2
Scaling nginx2 down to 3
Scaling nginx up to 3
Scaling nginx2 down to 2
Scaling nginx up to 4
Scaling nginx2 down to 1
Scaling nginx up to 5
Scaling nginx2 down to 0
Update succeeded. Deleting nginx2
replicationcontroller "nginx2" rolling updated to "nginx"
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE IP             NODE
nginx-4r223   1/1       Running   0          16s 172.18.100.4   10.0.0.13
nginx-8phch   1/1       Running   0          13s 172.18.100.3   10.0.0.13
nginx-dc8wc   1/1       Running   0          15s 172.18.100.2   10.0.0.13
nginx-kcmpv   1/1       Running   0          11s 172.18.100.5   10.0.0.13
nginx-mknrb   1/1       Running   0          9s  172.18.100.6   10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Mon, 07 Dec 2020 11:33:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

Service

service:提供服務的自動發現和負載均衡


Pod隨時會被銷毀和重新創建、並且每個Pod會通過調度器將其部署到不同的N個Node節點,這樣會導致Pod ip地址會發生變化。所以需要通過Service去發現Pod並獲取其IP地址。

K8s中三種Ip地址類型:Node ip、cluster ip、pod ip。

Pod使用RC(Replication Controller)實現高可用,會出現一些問題:

  • 只能在k8s的內部訪問,客戶端無法訪問,因為Pod IP是私有IP地址,外界無法訪問。

  • K8s中Node端口映射不可以直接映射到的Pod IP。如果一些Pod死掉了,RC就會創建一些新的Pod,新的Pod的ip地址會變化,此時做端口映射,修改規則很麻煩。

K8s使用Service資源,kube-proxy服務自動隨機分配固定不變的VIP(cluster ip),VIP地址段的范圍是10.254.0.0/16。Service資源幫助pod暴露端口。


Pod與Service的關系

  • 防止Pod失聯,獲取Pod信息(通過label-selector關聯)
  • 定義一組Pod的訪問策略(負載均衡 TCP/UDP 4層)
  • 支持ClusterIP,NodePort以及LoadBalancer 三種類型
  • Server的底層實現主要有iptables和IPVS二種網絡模式

每個Service關聯一個應用,每個Service資源自動關連一個同名endpoints資源。


Service類型

  • ClusterIP:默認,主要實現不同Pod之間互相訪問,是分配在一個集群內部,可以訪問的虛擬IP(vip)。
  • NodePort:在每個Node上分配一個端口作為外部訪問入口
  • LoadBalancer:工作在特定的Cloud Provider上,例如Google Cloud, AWS,OpenStack

  1. master節點編寫service資源yaml
mkdir -p /root/k8s_yaml/svc && cd /root/k8s_yaml/svc
cat > /root/k8s_yaml/svc/k8s_svc.yaml <<EOF
apiVersion: v1
kind: Service           # 簡稱svc
metadata:
  name: myweb
spec:
  type: NodePort        # 端口映射類型,默認ClusterIP類型
  #clusterIP:10.254.1.1
  ports:
    - port: 80          # clusterIP port
      nodePort: 30000   # node port 默認30000-32767
      targetPort: 80    # pod port
  selector:             # 選擇器。當有多個Pod的時候,需要使用選擇器選擇為那些Pod做負載均衡。和RC一樣,使用標簽選擇器。
    app: myweb
EOF
  1. master節點創建資源
kubectl create -f k8s_svc.yaml
  1. master節點查看所有svc資源狀態
[root@k8s-master svc]# kubectl get svc
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1     <none>        443/TCP        3d
myweb        10.254.238.3   <nodes>       80:30000/TCP   4s
[root@k8s-master svc]# kubectl describe svc
Name:			kubernetes
Namespace:		default
Labels:			component=apiserver
			provider=kubernetes
Selector:		<none>
Type:			ClusterIP
IP:			10.254.0.1
Port:			https	443/TCP
Endpoints:		10.0.0.11:6443
Session Affinity:	ClientIP
No events.


Name:			myweb
Namespace:		default
Labels:			<none>
Selector:		app=myweb
Type:			NodePort
IP:			10.254.73.4
Port:			<unset>	80/TCP
NodePort:		<unset>	30000/TCP
Endpoints:		172.18.100.2:80,172.18.100.3:80,172.18.100.4:80 + 2 more...
Session Affinity:	None
No events.
  1. master節點訪問node節點端口
[root@k8s-master svc]# curl -I http://10.0.0.12:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

[root@k8s-master svc]# curl -I http://10.0.0.13:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

service提供負載均衡

  1. master節點調整rc副本數量
kubectl scale rc nginx --replicas=3
  1. master節點進入3個pod容器,修改容器的首頁為不同頁面
kubectl get pod
kubectl exec -it pod_name1 /bin/bash
echo 'web01' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name2 /bin/bash
echo 'web02' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name3 /bin/bash
echo 'web03' > /usr/share/nginx/html/index.html
exit

pod中有多個業務容器,使用參數--container進入指定業務容器

kubectl exec --container=alpine -it test /bin/sh
  1. master節點驗證負載均衡
[root@k8s-master svc]# i=1;while ((i<=3));do curl http://10.0.0.12:30000;sleep 2;((i++));done
web02
web03
web01

service默認使用iptables實現四層負載均衡。

k8s 1.8版本推薦使用lvs(四層負載均衡 傳輸層tcp,udp)


service提供服務的自動發現

  1. master節點調整rc副本數量為2,查看pod
kubectl scale rc nginx --replicas=2
kubectl get pod
  1. master節點調整rc副本數量為3,查看pod
kubectl scale rc nginx --replicas=3
kubectl get pod

自定義nodePort范圍

sed -i "26c KUBE_API_ARGS=\"--service-node-port-range=3000-50000\"" /etc/kubernetes/apiserver
systemctl restart kube-apiserver.service

命令行創建service資源(node端口只能隨機)

kubectl expose rc nginx --type=NodePort --port=80 --target-port=80

service類型

第一種:NodePort類型

  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30008

第二種:ClusterIP類型,默認

  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

Deployment

rc在滾動升級之后,標簽改變,但service卻無法跟着改變,會造成服務訪問中斷,於是k8s引入了deployment資源。

Deployment 為PodReplicaSet之上,提供了一個聲明式定義(declarative)方法,替代以前的ReplicationController來方便的管理應用。
只需要在Deployment中描述您想要的目標狀態是什么,Deployment controller就會幫您將PodReplicaSet的實際狀態改變到您的目標狀態。可以定義一個新的Deployment來創建ReplicaSet或者刪除已有的 Deployment並創建一個新的來替換。也就是說Deployment是可以管理多個ReplicaSet的,如下圖:

img

雖然也 ReplicaSet 可以獨立使用,但建議使用 Deployment 來自動管理 ReplicaSet,這樣就無需擔心跟其他機制的不兼容問題。


  1. master節點編寫deployment資源yaml
mkdir -p /root/k8s_yaml/deploy && cd /root/k8s_yaml/deploy
cat > /root/k8s_yaml/deploy/k8s_deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  strategy:              # 策略
    rollingUpdate:       # 滾動升級
      maxSurge: 1        # 多啟動幾個容器
      maxUnavailable: 1  # 最大不可用的pod數量
    type: RollingUpdate
  minReadySeconds: 30    # 升級間隔最小秒
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        resources:        # 資源
          limits:         # 限制
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
EOF
  1. master節點創建資源
kubectl create -f k8s_deploy.yaml
  1. master節點查看資源狀態
[root@k8s-master deploy]# kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            0           3s
[root@k8s-master deploy]# kubectl get pod --show-labels
NAME                     READY     STATUS    RESTARTS   AGE       LABELS
nginx-2807576163-3550z   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-2807576163-bmxmz   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-2807576163-pt83k   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-8phch              1/1       Running   1          15h       app=myweb
nginx-dc8wc              1/1       Running   1          15h       app=myweb
nginx-twk24              1/1       Running   0          1h        app=myweb
[root@k8s-master deploy]# kubectl get all
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/nginx   3         3         3            3           41m

NAME       DESIRED   CURRENT   READY     AGE
rc/nginx   3         3         3         16h

NAME             CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc/kubernetes   10.254.0.1       <none>        443/TCP        3d
svc/myweb        10.254.73.4      <nodes>       80:30000/TCP   2h
svc/nginx        10.254.185.133   <nodes>       80:31504/TCP   38m

NAME                  DESIRED   CURRENT   READY     AGE
rs/nginx-2807576163   0         0         0         41m
rs/nginx-3014407781   3         3         3         34m

NAME                        READY     STATUS    RESTARTS   AGE
po/nginx-3014407781-4j9ld   1/1       Running   0          34m
po/nginx-3014407781-dbw3c   1/1       Running   0          30m
po/nginx-3014407781-prlzh   1/1       Running   0          34m
po/nginx-8phch              1/1       Running   1          16h
po/nginx-dc8wc              1/1       Running   1          16h
po/nginx-twk24              1/1       Running   0          2h

deployment滾動升級

deployment滾動升級不依賴配置文件,服務訪問不中斷;修改配置文件立即生效。

deployment升級時:更新了Pod,通過創建一個新的Replica Set(rc的升級版)並擴容3個replica,同時將原來的Replica Set縮容到0個replica。

下次更新這些pod的時候,只需要更新Deployment中的pod的template即可。

Deployment可以保證在升級時只有一定數量的Pod是down的。默認maxUnavailable: 1(最多一個不可用)。

Deployment同時也可以確保只創建出超過期望數量的一定數量的Pod。默認maxSurge: 1(最多1個surge)。


  1. 命令行創建service資源
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
  1. 查看service資源映射node端口
[root@k8s-master deploy]# kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1       <none>        443/TCP        3d
myweb        10.254.73.4      <nodes>       80:30000/TCP   1h
nginx        10.254.185.133   <nodes>       80:31504/TCP   19s
  1. 升級:修改deployment配置文件。僅需要修改鏡像版本
kubectl edit deployment nginx
  1. 訪問驗證:升級過程中新老版本可以同時訪問
i=1;while ((i<=3));do curl -I 10.0.0.12:31504;sleep 1;((i++));done

deployment升級和回滾

命令行創建deployment(--record 記錄版本變更原因)

kubectl run nginx --image=10.0.0.11:5000/nginx:1.13 --replicas=3 --record

命令行滾動升級版本

kubectl set image deployment nginx nginx=10.0.0.11:5000/nginx:1.15

pod中有多個業務容器,指定業務容器名稱alpine=10.0.0.11:5000/alpine:1.15

查看deployment所有歷史版本

kubectl rollout history deployment nginx

deployment回滾到上一個版本

kubectl rollout undo deployment nginx

deployment回滾到指定版本

kubectl rollout undo deployment nginx --to-revision=2

間章:練習

k8s中容器之間通過VIP相互訪問

tomcat+mysql:2個deployment資源和2個service資源。tomcat訪問mysql的svc提供的VIP

  1. node節點下載鏡像,上傳至私有倉庫
docker pull tomcat-app:v2
docker tag docker.io/kubeguide/tomcat-app:v2 10.0.0.11:5000/tomcat-app:v2
docker push 10.0.0.11:5000/tomcat-app:v2
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
  1. master節點創建配置文件
mkdir -p /root/k8s_yaml/tomcat_demo && cd /root/k8s_yaml/tomcat_demo
cat > /root/k8s_yaml/tomcat_demo/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
cat > /root/k8s_yaml/tomcat_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /root/k8s_yaml/tomcat_demo/tomcat-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 1
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
        - name: myweb
          image: 10.0.0.11:5000/tomcat-app:v2
          ports:
          - containerPort: 8080
          env:
          - name: MYSQL_SERVICE_HOST
            value: 'mysql'
          - name: MYSQL_SERVICE_PORT
            value: '3306'
EOF
cat > /root/k8s_yaml/tomcat_demo/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  type: NodePort
  ports:
    - port: 8080
      nodePort: 30008
  selector:
    app: myweb
EOF
  1. master節點創建mysql的rc和svc資源
kubectl create -f mysql-rc.yml
kubectl create -f mysql-svc.yml
  1. master節點查看所有svc資源
[root@k8s-master tomcat_demo]# kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1       <none>        443/TCP        3d
mysql        10.254.37.112    <none>        3306/TCP       18s
myweb        10.254.73.4      <nodes>       80:30000/TCP   5h
nginx        10.254.185.133   <nodes>       80:31504/TCP   3h
  1. master節點刪除已有同名svc資源myweb
kubectl delete svc myweb
  1. master節點修改tomcat的rc資源配置文件,修改變量MYSQL_SERVICE_HOST的值為mysql的VIP
vim tomcat-rc.yml
  1. master節點創建tomcat的rc和svc資源
kubectl create -f tomcat-rc.yml 
kubectl create -f tomcat-svc.yml
  1. 訪問:http://10.0.0.12:30008/demo/

image-20201208152415164


資源創建流程

創建pod資源流程:

  • 用戶和 api-server 交互,使用創建命令 kubectl create -f .
  • api-server 檢查yaml文件語法
    • 錯誤,報錯
    • 正確寫入etcd數據庫
  • api-server 調用 scheduler
    • 沒有可用node,Pending
    • 調度成功,返回name給api-server
  • api-server調用kubelet,發送pod配置文件

刪除pod資源流程:

  • 用戶和 api-server 交互,使用創建命令 kubectl delete pod nginx
  • api-server 修改etcd數據庫中pod的狀態
  • api-server調用kubelet停止並刪除容器
    • 調用失敗,Unkown
  • 調用成功,api-server刪除etcd數據庫中pod的記錄

創建deployment資源流程:

  • 用戶和 api-server 交互,使用創建命令 kubectl create -f .
  • api-server 檢查yaml文件語法
    • 錯誤,報錯
    • 正確寫入etcd數據庫
  • controller-manager創建rs
  • controller-manager申請創建pod
  • api-server 調用 scheduler
    • 沒有可用node,Pending
    • 調度成功,返回name給api-server
  • api-server調用kubelet,發送pod配置文件

DaemonSet

不需要指定副本數,有幾個node節點創建幾個。

在一個區域(zone)或者所有Node上運行同一個守護進程(pod)

  • 每個Node上運行一個分布式存儲的守護進程,例如glusterd,ceph等。
  • 日志采集器運行在每個Node上,例如fluentd,logstash等。
  • 監控的采集端運行在每個Node,例如prometheus node exporter,collectd等。

DaemonSet的Pod調度策略與RC類似,除了使用系統內置的調度算法在每個Node上進行調度,也可以在Pod定義中使用NodeSelector或NodeAffinity來指定滿足條件的Node范圍進行調度。

注意:各資源labels不能一致!否則會導致pod一直刪除再創建死循環。

mkdir -p /root/k8s_yaml/daemonset && cd /root/k8s_yaml/daemonset
cat > /root/k8s_yaml/daemonset/k8s_daemonset.yaml <<EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: oldboy
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
EOF
kubectl create -f k8s_daemonset.yaml
kubectl get pod -o wide

其他資源

  • StatefulSet (PetSets)
    • StatefulSet (PetSets):寵物應用,有狀態的應用,pod名稱固定(有序 01 02 03),適用於每個Pod中有自己的編號,需要互相訪問,以及持久存儲區分。例如數據庫應用,redis,ES集群,mysql集群
    • 其他資源:畜生應用,無狀態的應用,pod名稱隨機
  • Jobs
    • Jobs:一次性任務,完成狀態complate
    • Pod:一直運行
  • Cronjobs:定時任務
  • Ingress
    • Ingress:七層負載均衡
    • Service:四層負載均衡
  • Secret:密碼,密鑰
  • ConfigMaps:配置文件

資源總結

img

k8s資源 作用
daemonSet 用來描述每個宿主機上必須且只能運行一個副本的守護進程服務
Job 用來描述一次性運行的 Pod(比如,大數據任務)
CronJob 用於描述定時任務

k8s附加組件

DNS服務

DNS服務:將svc的名稱解析成對應VIP地址

  1. node2節點(10.0.0.13)下載鏡像,並導入(4個鏡像,來自google倉庫)
[root@k8s-node-2 ~]# docker load -i docker_k8s_dns.tar.gz
8ac8bfaff55a: Loading layer 1.293 MB/1.293 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
b79219965469: Loading layer 45.91 MB/45.91 MB
Loaded image: gcr.io/google_containers/kubedns-amd64:1.9
3fc666989c1d: Loading layer 5.046 MB/5.046 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
9eed5e14d7fb: Loading layer 348.7 kB/348.7 kB
00dc4ffe8624: Loading layer  2.56 kB/2.56 kB
Loaded image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
9007f5987db3: Loading layer  5.05 MB/5.05 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
d41159f2130e: Loading layer 9.201 MB/9.201 MB
Loaded image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
dc978cfc3e09: Loading layer 7.279 MB/7.279 MB
99740866972b: Loading layer 7.168 kB/7.168 kB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
Loaded image: gcr.io/google_containers/exechealthz-amd64:1.2
  1. master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/dns && cd /root/k8s_yaml/dns
cat > /root/k8s_yaml/dns/skydns-svc.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*

# Warning: This is a file generated from the base underscore template file: skydns-svc.yaml.base

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.254.230.254
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
EOF
cat > /root/k8s_yaml/dns/skydns.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml
# in sync with this file.

# __MACHINE_GENERATED_WARNING__

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  # replicas: not specified here:
  # 1. In order to make Addon Manager do not reconcile this replicas parameter.
  # 2. Default is 1.
  # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 0
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      nodeName: 10.0.0.13  # 指定調度到的node
      containers:
      - name: kubedns
        image: gcr.io/google_containers/kubedns-amd64:1.9
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthz-kubedns
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        - --domain=cluster.local.
        - --dns-port=10053
        - --config-map=kube-dns
        - --kube-master-url=http://10.0.0.11:8080
        # This should be set to v=2 only after the new image (cut from 1.5) has
        # been released, otherwise we will flood the logs.
        - --v=0
        #__PILLAR__FEDERATIONS__DOMAIN__MAP__
        env:
        - name: PROMETHEUS_PORT
          value: "10055"
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
        - containerPort: 10055
          name: metrics
          protocol: TCP
      - name: dnsmasq
        image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
        livenessProbe:
          httpGet:
            path: /healthz-dnsmasq
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=127.0.0.1 # 10053
        #- --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
        resources:
          requests:
            cpu: 150m
            memory: 10Mi
      - name: dnsmasq-metrics
        image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
        livenessProbe:
          httpGet:
            path: /metrics
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --v=2
        - --logtostderr
        ports:
        - containerPort: 10054
          name: metrics
          protocol: TCP
        resources:
          requests:
            memory: 10Mi
      - name: healthz
        image: gcr.io/google_containers/exechealthz-amd64:1.2
        resources:
          limits:
            memory: 50Mi
          requests:
            cpu: 10m
            # Note that this container shouldn't really need 50Mi of memory. The
            # limits are set higher than expected pending investigation on #29688.
            # The extra memory was stolen from the kubedns container to keep the
            # net memory requested by the pod constant.
            memory: 50Mi
        args:
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - --url=/healthz-dnsmasq
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
        - --url=/healthz-kubedns
        - --port=8080
        - --quiet
        ports:
        - containerPort: 8080
          protocol: TCP
      dnsPolicy: Default  # Don't use cluster DNS.
EOF
  1. master節點創建DNS的資源
kubectl create -f .
  1. master節點檢查命名空間kube-system
kubectl get namespace
kubectl get all -n kube-system -o wide
[root@k8s-master dns]# kubectl get all -n kube-system
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/kube-dns   1         1         1            1           10m

NAME           CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
svc/kube-dns   10.254.230.254   <none>        53/UDP,53/TCP   10m

NAME                    DESIRED   CURRENT   READY     AGE
rs/kube-dns-249145955   1         1         1         10m

NAME                          READY     STATUS    RESTARTS   AGE
po/kube-dns-249145955-wdmq8   4/4       Running   0          10m
  1. 所有node節點修改kubelet配置文件,重啟服務
sed -i '20c KUBELET_ARGS=\"--cluster_dns=10.254.230.254 --cluster_domain=cluster.local\"'  /etc/kubernetes/kubelet
systemctl restart kubelet
  1. master節點修改tomcat的rc資源配置文件,修改變量MYSQL_SERVICE_HOST的值為mysql,重新創建資源
cd /root/k8s_yaml/tomcat_demo
vim tomcat-rc.yml
kubectl delete -f .
kubectl create -f .
  1. master節點驗證
[root@k8s-master tomcat_demo]# kubectl get pod # 查找myweb容器名
NAME                     READY     STATUS    RESTARTS   AGE
mysql-sj480              1/1       Running   0          3m
myweb-th9rx              1/1       Running   0          1m
[root@k8s-master tomcat_demo]# kubectl exec -it myweb-th9rx /bin/bash #進入容器
root@myweb-th9rx:/usr/local/tomcat# cat /etc/resolv.conf # 查看DNS解析
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.254.230.254
nameserver 223.5.5.5
options ndots:5
root@myweb-th9rx:/usr/local/tomcat# ping mysql # 能解析,不能ping通,VIP
PING mysql.default.svc.cluster.local (10.254.106.204): 56 data bytes
^C--- mysql.default.svc.cluster.local ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
root@myweb-th9rx:/usr/local/tomcat# exit
exit

namespace命名空間

namespace:實現資源隔離

  1. 查看命名空間
kubectl get namespace
  1. 創建命名空間
kubectl create namespace tomcat
  1. 修改配置文件指定命名空間
cd /root/k8s_yaml/tomcat_demo/
sed -i "3a \ \ namespace: tomcat" *
yum install dos2unix -y
dos2unix *
  1. 刪除所有svc和rc資源
kubectl delete svc --all
kubectl delete rc --all
  1. 創建rc和svc資源
kubectl create -f .
  1. 查看命名空間tomcat的所有資源
kubectl get all -n tomcat

間章:作業

k8s中容器之間通過VIP相互訪問,應用DNS,namespace

wordpress+mysql:2個deployment資源和2個service資源。wordpress訪問mysql的svc提供的VIP

  1. node下載鏡像,上傳至私有倉庫
docker pull wordpress
docker tag docker.io/wordpress:latest 10.0.0.11:5000/wordpress:latest
docker push 10.0.0.11:5000/wordpress:latest
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
  1. 創建rc和svc配置文件
mkdir -p /root/k8s_yaml/wordpress_rc && cd /root/k8s_yaml/wordpress_rc
cat > /root/k8s_yaml/wordpress_rc/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
cat > /root/k8s_yaml/wordpress_rc/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /root/k8s_yaml/wordpress_rc/wordpress-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  selector:
    app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
cat > /root/k8s_yaml/wordpress_rc/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
  selector:
    app: wordpress
EOF

查看系統補全的配置文件

kubectl get pod NAME -n NAMESPACE -o yaml

鏡像拉取策略

[root@k8s-master ~]# kubectl explain pod.spec.containers.imagePullPolicy
FIELD: imagePullPolicy <string>

DESCRIPTION:
Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.
More info: http://kubernetes.io/docs/user-guide/images#updating-images
Always       每次創建Pod都會重新拉取一次鏡像
Never        Pod永遠不會主動拉取這個鏡像
IfNotPresent 默認值,鏡像在宿主機上不存在時才拉取
  1. 刪除所有資源
kubectl delete svc --all
kubectl delete rc --all
kubectl delete deployment --all
  1. 創建命名空間
kubectl create namespace wordpress
  1. 創建資源
kubectl create -f .
  1. 查看svc資源,訪問:http://10.0.0.12:30080/
kubectl get all -n wordpress -o wide
  1. 創建deploy和svc配置文件
mkdir -p /root/k8s_yaml/wordpress_demo && cd /root/k8s_yaml/wordpress_demo
cat > /root/k8s_yaml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
cat > /root/k8s_yaml/wordpress_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /root/k8s_yaml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
cat > /root/k8s_yaml/wordpress_demo/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
  selector:
    app: wordpress
EOF

健康檢查和可用性檢查

探針種類:

livenessProbe:健康狀態檢查,周期性檢查服務是否存活,檢查結果失敗,自動重啟容器。

readinessProbe:可用性檢查,周期性檢查服務是否可用,不可用將從service的endpoints中移除。

探針檢測方法:

  • exec:執行一段命令,返回值為0正常,非0錯誤。
  • httpGet:檢測某個 http 請求的返回狀態碼 2xx,3xx正常;4xx,5xx錯誤。
  • tcpSocket:測試某個端口是否能夠連接。

liveness探針的exec使用

mkdir -p /root/check/ && cd /root/check/
cat > /root/check/nginx_pod_exec.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: exec
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
      livenessProbe:            # 模擬健康檢查,啟動后30s內健康,之后不健康
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 5   # 初始化5秒后開始檢查
        periodSeconds: 5         # 檢查周期5s一次
        timeoutSeconds: 3        # 檢查命令執行超時時間,默認1s
        successThreshold: 1      # 檢查成功1次就算成功,默認1次
        failureThreshold: 1      # 檢查失敗1次就算失敗,默認3次
EOF
kubectl create -f nginx_pod_exec.yaml
kubectl describe pod exec
mysqladmin ping  # 檢測mysql存活

liveness探針的httpGet使用

cat > /root/check/nginx_pod_httpGet.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: httpget
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      livenessProbe:
        httpGet:
          path: /index.html
          port: 80
        initialDelaySeconds: 3
        periodSeconds: 3
EOF
kubectl create -f nginx_pod_httpGet.yaml
kubectl describe pod httpget
kubectl exec -it httpget /bin/bash
rm -f /usr/share/nginx/html/index/html
exit
kubectl describe pod httpget

liveness探針的tcpSocket使用

cat > /root/check/nginx_pod_tcpSocket.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: tcpsocket
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - tail -f /etc/hosts
      livenessProbe:
        tcpSocket:
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 3
EOF
kubectl create -f nginx_pod_tcpSocket.yaml
kubectl describe pod tcpsocket
kubectl exec -it tcpsocket /bin/bash
nginx -s stop
exit
kubectl describe pod tcpsocket

readiness探針的httpGet使用

cat > /root/check/nginx_rc_httpGet.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: readiness
spec:
  replicas: 2
  selector:
    app: readiness
  template:
    metadata:
      labels:
        app: readiness
    spec:
      containers:
      - name: readiness
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /qiangge.html
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 3
EOF
kubectl create -f nginx_rc_httpGet.yaml
kubectl expose rc readiness --type=NodePort --port=80 --target-port=80
kubectl describe svc readiness
kubectl get pod
kubectl exec -it readiness-NAME /bin/bash
echo 'web' > /usr/share/nginx/html/qiangge.html
exit
kubectl get pod
kubectl describe svc readiness

Dashboard服務

  1. node2節點(10.0.0.13)下載鏡像,並導入,打標(來自tenxcloud倉庫)
[root@k8s-node-2 opt]# docker load -i kubernetes-dashboard-amd64_v1.4.1.tar.gz 
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
2e350fa8cbdf: Loading layer 86.96 MB/86.96 MB
Loaded image: index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1
[root@k8s-node-2 opt]# docker tag index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
  1. master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/dashboard/ && cd /root/k8s_yaml/dashboard/
cat > /root/k8s_yaml/dashboard/dashboard.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# Keep the name in sync with image version and
# gce/coreos/kube-manifests/addons/dashboard counterparts
  name: kubernetes-dashboard-latest
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
        version: latest
        kubernetes.io/cluster-service: "true"
    spec:
      nodeName: 10.0.0.13  # 指定調度到的node
      containers:
      - name: kubernetes-dashboard
        image: 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
        ports:
        - containerPort: 9090
        args:
         -  --apiserver-host=http://10.0.0.11:8080
        livenessProbe:
          httpGet:
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
EOF
cat > /root/k8s_yaml/dashboard/dashboard-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  labels:
    k8s-app: kubernetes-dashboard
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: kubernetes-dashboard
  ports:
  - port: 80
    targetPort: 9090
EOF
  1. master節點創建dashboard的資源
kubectl create -f .
  1. master節點檢查命名空間kube-system
kubectl get all -n kube-system
  1. 訪問http://10.0.0.11:8080/ui/

全局資源

  • Namespaces
  • Nodes
  • Persistemt Volume Claims

局部資源(各Namespaces分別使用的資源)


通過apiservice反向代理訪問service資源

  1. 分析dashboard服務web頁面

    主頁+錨點(#)

http://10.0.0.11:8080/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#/workload?namespace=default
  1. 查看所有命名空間的svc
kubectl get svc --all-namespaces
  1. 通過apiservice反向代理訪問service資源
http://10.0.0.11:8080/api/v1/proxy/namespaces/命名空間名稱/services/service名稱/

彈性伸縮

Kubernetes HPA(Horizontal Pod Autoscaler)Pod 水平自動擴縮:可以基於 CPU 利用率自動擴縮 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 數量。 除了 CPU 利用率,也可以基於其他應程序提供的自定義度量指標來執行自動擴縮。 但不適用於無法擴縮的對象,比如 DaemonSet。

Pod 水平自動擴縮特性由 Kubernetes API 資源和控制器實現。資源決定了控制器的行為。 控制器會周期性的調整副本控制器或 Deployment 中的副本數量,以使得 Pod 的平均 CPU 利用率與用戶所設定的目標值匹配。

Pod水平自動伸縮:

  • 1.11版本之前,依賴heapster監控各node節點信息。
  • 1.11版本之后,使用metric-server采集指標信息。

HPA工作機制

image-20201209163836720


安裝heapster監控

k8s原生集群監控方案(Heapster+InfluxDB+Grafana+Dashboard) :

Heapster處理數據儲存到InfluxDB,Grafana從InfluxDB讀取數據出圖,Dashboard調用Grafana的圖。

image-20201209194647502

  1. node2節點(10.0.0.13)下載鏡像,並導入,打標(3個鏡像,來自官方倉庫)
for n in `ls *.tar.gz`;do docker load -i $n ;done
docker tag docker.io/kubernetes/heapster_grafana:v2.6.0 10.0.0.11:5000/heapster_grafana:v2.6.0
docker tag  docker.io/kubernetes/heapster_influxdb:v0.5 10.0.0.11:5000/heapster_influxdb:v0.5
docker tag docker.io/kubernetes/heapster:canary 10.0.0.11:5000/heapster:canary
  1. master節點創建配置文件(指定調度到node2)
mkdir -p /root/k8s_yaml/heapster-influxdb && cd /root/k8s_yaml/heapster-influxdb
cat > /root/k8s_yaml/heapster-influxdb/heapster-controller.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    k8s-app: heapster
    name: heapster
    version: v6
  name: heapster
  namespace: kube-system
spec:
  replicas: 1
  selector:
    k8s-app: heapster
    version: v6
  template:
    metadata:
      labels:
        k8s-app: heapster
        version: v6
    spec:
      nodeName: 10.0.0.13  # 指定調度到的node
      containers:
      - name: heapster
        image: 10.0.0.11:5000/heapster:canary
        #imagePullPolicy: Always
        command:
        - /heapster
        - --source=kubernetes:http://10.0.0.11:8080?inClusterConfig=false
        - --sink=influxdb:http://monitoring-influxdb:8086
EOF
cat > /root/k8s_yaml/heapster-influxdb/influxdb-grafana-controller.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    name: influxGrafana
  name: influxdb-grafana
  namespace: kube-system
spec:
  replicas: 1
  selector:
    name: influxGrafana
  template:
    metadata:
      labels:
        name: influxGrafana
    spec:
      nodeName: 10.0.0.13  # 指定調度到的node
      containers:
      - name: influxdb
        image: 10.0.0.11:5000/heapster_influxdb:v0.5
        volumeMounts:
        - mountPath: /data
          name: influxdb-storage
      - name: grafana
        image: 10.0.0.11:5000/heapster_grafana:v2.6.0
        env:
          - name: INFLUXDB_SERVICE_URL
            value: http://monitoring-influxdb:8086
            # The following env variables are required to make Grafana accessible via
            # the kubernetes api-server proxy. On production clusters, we recommend
            # removing these env variables, setup auth for grafana, and expose the grafana
            # service using a LoadBalancer or a public IP.
          - name: GF_AUTH_BASIC_ENABLED
            value: "false"
          - name: GF_AUTH_ANONYMOUS_ENABLED
            value: "true"
          - name: GF_AUTH_ANONYMOUS_ORG_ROLE
            value: Admin
          - name: GF_SERVER_ROOT_URL
            value: /api/v1/proxy/namespaces/kube-system/services/monitoring-grafana/
        volumeMounts:
        - mountPath: /var
          name: grafana-storage
      volumes:
      - name: influxdb-storage
        emptyDir: {}
      - name: grafana-storage
        emptyDir: {}
EOF
cat > /root/k8s_yaml/heapster-influxdb/grafana-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  labels:
    kubernetes.io/cluster-service: 'true'
    kubernetes.io/name: monitoring-grafana
  name: monitoring-grafana
  namespace: kube-system
spec:
  # In a production setup, we recommend accessing Grafana through an external Loadbalancer
  # or through a public IP. 
  # type: LoadBalancer
  ports:
  - port: 80
    targetPort: 3000
  selector:
    name: influxGrafana
EOF
cat > /root/k8s_yaml/heapster-influxdb/influxdb-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  labels: null
  name: monitoring-influxdb
  namespace: kube-system
spec:
  ports:
  - name: http
    port: 8083
    targetPort: 8083
  - name: api
    port: 8086
    targetPort: 8086
  selector:
    name: influxGrafana
EOF
cat > /root/k8s_yaml/heapster-influxdb/heapster-service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  labels:
    kubernetes.io/cluster-service: 'true'
    kubernetes.io/name: Heapster
  name: heapster
  namespace: kube-system
spec:
  ports:
  - port: 80
    targetPort: 8082
  selector:
    k8s-app: heapster
EOF
  1. master節點創建dashboard的資源
kubectl create -f .
  1. master節點檢查命名空間kube-system,查看集群信息
kubectl get all -n kube-system
kubectl cluster-info
  1. 瀏覽器訪問dashboard驗證http://10.0.0.11:8080/ui/

image-20201209163459528

  1. 可以使用top命令
kubectl top node

彈性伸縮

  1. master節點創建測試Deployment和svc資源
cd /root/k8s_yaml/deploy
cat > /root/k8s_yaml/deploy/k8s_deploy2.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
EOF
kubectl create -f k8s_deploy2.yaml
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80

  1. 創建彈性伸縮規則
kubectl autoscale deploy nginx --max=8 --min=1 --cpu-percent=5
  1. 查看hpa資源,nginx訪問地址IP:PORT
kubectl get all -o wide
  1. 查看hpa資源配置文件
kubectl get hpa nginx -o yaml
  1. 壓測
yum install httpd-tools -y
ab -n 1000000 -c 40 http://10.0.0.12:32114/index.html
  1. 驗證http://10.0.0.11:8080/ui/

壓測前:

image-20201209172019380

壓測10s后,自動擴容

image-20201209172134559

停止壓測5分鍾后,自動縮容:

image-20201209172743894

持久化存儲

查看解釋

kubectl explain pod.spec.containers.volumeMounts
kubectl explain pod.spec.volumes

持久化存儲類型:

  • emptyDir:共享pod生存期的臨時目錄。
  • hostPath:主機上預先存在的文件或目錄直接公開給容器。這通常用於允許查看主機的系統代理或其他特權對象。
  • nfs:共享pod生存期的NFS裝載。

emptyDir

臨時的空目錄:伴隨pod的生命周期,隨着pod刪除而刪除,數據持久化但不共享。

適用於存放日志(pod之間不同,但需要保存的數據)。

emptyDir是一種臨時存儲,pod創建的時候會在node節點上為容器申請一個臨時的目錄,跟隨容器的生命周期,若容器刪除,emptyDir定義的臨時存儲空間也會隨之刪除,容器發生意外crash則不受影響,同時如果容器發生了遷移,其上的數據也會丟失,emptyDir一般用於測試,或者緩存場景。注意:容器崩潰不會導致數據的丟失,因為容器的崩潰並不移除pod.

emptyDir 的一些用途:

  • 緩存空間,例如基於磁盤的歸並排序。
  • 為耗時較長的計算任務提供檢查點,以便任務能方便地從崩潰前狀態恢復執行。
  • 在 Web 服務器容器服務數據時,保存內容管理器容器獲取的文件。

image-20201210135509124


  1. 創建tomcat+mysql的資源
cd /root/k8s_yaml/tomcat_demo && kubectl create -f .
  1. 訪問:http://10.0.0.12:30008/demo/,添加數據
  2. node節點清空容器,雖然會重啟一批容器,但之前添加的數據沒了,因此需要持久化存儲
docker rm -f `docker ps -aq`
  1. master節點創建emptyDir持久化配置文件
cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        emptyDir: {}
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master節點刪除原rc資源,創建emptyDir持久化的rc資源
kubectl delete -f mysql-rc.yml
kubectl create -f mysql-emptyDir.yml
  1. node節點查看臨時目錄
ll /var/lib/kubelet/pods/
ll /var/lib/kubelet/pods/sha256號/volumes/kubernetes.io~empty-dir/mysql

刪除pod,這個文件也會自動刪除。


HostPath

HostPath:可以多個容器共享持久化數據,但不能跨宿主機。

hostPath 卷能將node宿主機節點文件系統上的文件或目錄掛載到您的 Pod 中。

  • 運行一個需要訪問 Docker 引擎內部機制的容器;請使用 hostPath 掛載 /var/lib/docker 路徑。
  • 在容器中運行 cAdvisor 時,以 hostPath 方式掛載 /sys
  • 允許 Pod 指定給定的 hostPath 在運行 Pod 之前是否應該存在,是否應該創建以及應該以什么方式存在。

使用這種類型的卷時要小心,因為:

  • 具有相同配置(例如從 podTemplate 創建)的多個 Pod 會由於節點上文件的不同而在不同節點上有不同的行為。
  • 當 Kubernetes 按照計划添加資源感知的調度時,這類調度機制將無法考慮由 hostPath 使用的資源。
  • 基礎主機上創建的文件或目錄只能由 root 用戶寫入。您需要在特權容器中以 root 身份運行進程,或者修改主機上的文件權限以便容器能夠寫入 hostPath 卷。

  1. master節點創建wordpress+mysql資源
cd /root/k8s_yaml/wordpress_demo
kubectl create namespace wordpress
kubectl create -f .
  1. master節點持久化mysql
cat > /root/k8s_yaml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        emptyDir: {}
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
  1. master節點應用配置文件:新建一個資源,此次不適用
kubectl apply -f mysql-demo.yml
kubectl get pod -o wide -n wordpress
kubectl delete deploy -n wordpress --all
kubectl create -f mysql-demo.yml
kubectl create -f wordpress-demo.yml
  1. master節點持久化wordpress
cat > /root/k8s_yaml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: wp-code
        hostPath:
          path: /data/wp-code
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
          - name: wp-code
            mountPath: /var/www/html
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
  1. master節點替換配置文件,刪除所有pod生效
mkdir -p /data/wp-code
kubectl replace -f wordpress-demo.yml
kubectl delete pod -n wordpress --all 
kubectl get pod -o wide -n wordpress
  1. 安裝wordpresshttp://10.0.0.12:30080/

  2. node1(10.0.0.12)節點查看持久化目錄

ll /data/wp-code
  1. wordpress上傳圖片

  2. node1查看上傳圖片

ll /data/wp-code/wp-content/uploads/

刪除pod時,文件不會刪除掉,還要保存到node上。

  1. master節點修改副本數
kubectl scale -n wordpress deployment wordpress --replicas=2
  1. master節點查看pod資源
kubectl get pod -o wide -n wordpress
  1. node1創建phpinfo頁面
echo "<?php phpinfo() ?>" > /data/wp-code/info.php
  1. 訪問phpinfo頁面,驗證調度到多個pod,但共享數據
curl 10.0.0.12:30080/info.php | grep -i 172.18.98

NFS

NFS:可以多個容器跨宿主機共享持久化數據。

  1. 所有節點安裝nfs-utils
yum -y install nfs-utils
  1. master節點部署nfs服務
mkdir -p /data/tomcat-db
cat > /etc/exports <<EOF
/data    10.0.0.0/24(rw,sync,no_root_squash,no_all_squash)
EOF
systemctl start nfs
  1. 所有node節點檢查掛載
showmount -e 10.0.0.11
  1. master節點創建nfs持久化配置文件
cd /root/k8s_yaml/tomcat_demo
cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
      - name: mysql
        nfs:
          path: /data/tomcat-db
          server: 10.0.0.11
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master節點替換配置文件,刪除所有pod生效
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
  1. node1查看nfs掛載
df -Th|grep nfs
  1. 訪問:http://10.0.0.12:30008/demo/,添加數據

  2. master節點修改配置文件:調度到13上

cat > /root/k8s_yaml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.13
      volumes:
      - name: mysql
        nfs:
          path: /data/tomcat-db
          server: 10.0.0.11
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master節點替換配置文件,刪除所有pod生效
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
  1. node2查看nfs掛載
df -Th|grep nfs
  1. 訪問:http://10.0.0.13:30008/demo/,數據還在

PV和PVC

PersistentVolume(持久化卷):全局資源,是對底層的共享存儲的一種抽象。PV 由管理員進行創建和配置,它和具體的底層的共享存儲技術的實現方式有關,比如 Ceph、GlusterFS、NFS 等,都是通過插件機制完成與共享存儲的對接。

PersistentVolumeClaim(持久化卷聲明):局部資源,屬於某一個namespace。PVC 是用戶存儲的一種聲明,PVC 和 Pod 比較類似,Pod 消耗的是節點,PVC 消耗的是 PV 資源,Pod 可以請求 CPU 和內存,而 PVC 可以請求特定的存儲空間和訪問模式。對於真正使用存儲的用戶不需要關心底層的存儲實現細節,只需要直接使用 PVC 即可。

img

  • Volumes:最基礎的存儲抽象,其支持多種類型,包括本地存儲、NFS、FC以及眾多的雲存儲,我們也可以編寫自己的存儲插件來支持特定的存儲系統。Volume可以被Pod直接使用,也可以被PV使用。普通的Volume和Pod之間是一種靜態的綁定關系,在定義Pod的同時,通過volume屬性來定義存儲的類型,通過volumeMount來定義容器內的掛載點。
  • PersistentVolume:是Kubernetes中的一個資源對象,創建一個PV相當於創建了一個存儲資源對象,這個資源的使用要通過PVC來請求。
  • PersistentVolumeClaim:是用戶對存儲資源PV的請求,根據PVC中指定的條件Kubernetes動態的尋找系統中的PV資源並進行綁定。目前PVC與PV匹配可以通過StorageClassName、matchLabels或者matchExpressions三種方式。
  • StorageClass:存儲類,目前kubernetes支持很多存儲,例如ceph,nfs。glusterfs等。

生命周期

PV是集群中的資源。PVC是對這些資源的請求,也是對資源的索賠檢查。 PV和PVC之間的相互作用遵循這個生命周期:Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

img

PVC 處理流程

圖片.png


Provisioning

PV的提供方式:靜態或者動態。

  • Static:集群管理員創建多個PV。 它們攜帶可供集群用戶使用的真實存儲的詳細信息。 它們存在於Kubernetes API中,可用於消費。
  • Dynamic:當管理員創建的靜態PV都不匹配用戶的PersistentVolumeClaim時,集群可能會嘗試為PVC動態配置卷。 此配置基於StorageClasses:PVC必須請求一個類,並且管理員必須已創建並配置該類才能進行動態配置。 要求該類的聲明有效地為自己禁用動態配置。

Provisioning


PV訪問模式

  • RWO - ReadWriteOnce——該卷可以被單個節點以讀/寫模式掛載
  • ROX - ReadOnlyMany——該卷可以被多個節點以只讀模式掛載
  • RWX - ReadWriteMany——該卷可以被多個節點以讀/寫模式掛載

zp7dytnfgz


  1. master節點創建svc配置文件
mkdir -p /root/k8s_yaml/volume && cd /root/k8s_yaml/volume
cat > /root/k8s_yaml/volume/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: tomcat
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /root/k8s_yaml/volume/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: tomcat
  name: myweb
spec:
  type: NodePort
  ports:
    - port: 8080
      nodePort: 30008
  selector:
    app: myweb
EOF
  1. master節點創建pv配置文件
mkdir -p mkdir -p /data/pv{1,2,3}
cat > /root/k8s_yaml/volume/pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels:
    type: nfs001
spec:
  capacity:
    storage: 10Gi                         # 不會去驗證是否真的有這么多空間
  accessModes:
    - ReadWriteMany                       # 允許多個pod讀寫,實現共享
  persistentVolumeReclaimPolicy: Recycle  # 回收策略:回收
  nfs:
    path: "/data/pv1"
    server: 10.0.0.11
    readOnly: false
EOF
cat > /root/k8s_yaml/volume/pv2.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
  labels:
    type: nfs001
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/pv2"
    server: 10.0.0.11
    readOnly: false
EOF
cat > /root/k8s_yaml/volume/pv3.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
  labels:
    type: ssd
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/pv3"
    server: 10.0.0.11
    readOnly: false
EOF

回收策略:

kubectl explain persistentvolumes.spec.persistentVolumeReclaimPolicy
  • Retain(保留):手動回收pv。默認

  • Recycle(回收):基本擦除pv( rm -rf /thevolume/* )

  • Delete(刪除):關聯的存儲資產(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷) 將被刪除

    當前,只有 NFS 和 HostPath 支持回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持刪除策略

  1. master節點創建pv資源
kubectl create namespace tomcat
kubectl create -f .
  1. master節點查看pv資源
kubectl get pv

pv卷狀態:

  • Available(可用):一塊空閑資源還沒有被任何聲明綁定
  • Bound(已綁定):卷已經被聲明綁定
  • Released(已釋放):聲明被刪除,但是資源還未被集群重新聲明
  • Failed(失敗):該卷的自動回收失敗 命令行會顯示綁定到 PV 的 PVC 的名稱
  1. master節點創建pvc配置文件
cat > /root/k8s_yaml/volume/mysql_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: tomcat
  name: tomcat-mysql
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 30Gi
EOF
  1. master節點創建pvc資源
kubectl create -f mysql_pvc.yaml
  1. master節點查看pv和pvc資源
kubectl get pv
kubectl get pvc -n tomcat
  1. master節點創建Deployment資源:pod模板里使用volume
cat > /root/k8s_yaml/volume/mysql-rc.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: tomcat
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        persistentVolumeClaim:
          claimName: tomcat-mysql
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master節點創建pvc資源
kubectl create -f mysql-rc.yml
  1. master節點驗證pv和pvc資源的使用
kubectl get pv 
kubectl get pod -n tomcat
kubectl describe pod -n tomcat mysql-k90jm | grep -i persistentVolumeClaim
kubectl describe pod -n tomcat mysql-k90jm | grep -i tomcat-mysql

回收pv資源

  1. master節點刪除tomcat命名空間
kubectl delete namespace tomcat
  1. master節點查看pv處於回收狀態,會創建一個pod用來回收(鏡像在Google倉庫)
kubectl get pv
kubectl get pod
  1. master節點修改鏡像地址為阿里雲源
kubectl edit pod recycler-for-pv3
    image: registry.aliyuncs.com/google_containers/busybox:latest
  1. master節點查看pod正常運行
kubectl get pod
  1. master節點查看pv回收完畢,處於正常狀態
kubectl get pv

標簽選擇器(優先)

  1. master節點創建pv配置文件
cat > /root/k8s_yaml/volume/pv4.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv4
  labels:
    type: sata
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/pv4"
    server: 10.0.0.11
    readOnly: false
EOF
  1. master節點創建pv資源
kubectl create -f pv4.yaml
  1. master節點查看pv資源的標簽
kubectl get pv --show-labels
  1. master節點創建pvc配置文件:使用標簽選擇器
cat > /root/k8s_yaml/volume/mysql_pvc2.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: tomcat-mysql
spec:
  selector:
    matchLabels:
      type: ssd
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
EOF
  1. master節點創建pvc資源
kubectl create -f mysql_pvc2.yaml
  1. master節點驗證pv資源優先使用標簽選擇器的指定
kubectl get pv --show-labels

Ceph

Storage:

  • 存儲硬件:nas,san

  • 存儲軟件:nfs,lvm

Storage方式

  • 塊存儲:提供硬盤,lvm,cinder
  • 文件存儲:提供目錄,nfs(單機存儲),glusterfs(分布式存儲)
  • 對象存儲:提供接口,fastdfs,Swift,ceph(分布式存儲)
存儲方式 技術實現 優勢 劣勢 代表作
塊存儲 裸盤上划分邏輯卷,邏輯卷格式化成任意文件系統 支持多種文件系統,傳輸速度快,提供硬件容錯機制 無法實現網絡共享 FC-SAN,iSCSI
文件存儲 在格式化的磁盤上存儲文件 提供網絡共享 網絡傳輸速度制約讀寫速度,分層目錄結構限制可擴展性 NFS,FAT,EXT3
對象存儲 以靈活可定制的對象為存儲單元,元數據服務器提供快速並發尋址 讀寫速度較快的同時支持網絡共享,對象靈活定義 管理軟件的購買、使用和運維成本高 Swift

塊存儲

典型設備: 磁盤陣列,硬盤

塊存儲主要是將裸磁盤空間整個映射給主機使用的。

通過划邏輯盤、做Raid、或者LVM(邏輯卷)等種種方式邏輯划分出N個邏輯的硬盤。

接着塊存儲會采用映射的方式將這幾個邏輯盤映射給主機,操作系統還需要對掛載的裸硬盤進行分區、格式化后,才能使用,與平常主機內置硬盤的方式完全無異。

優點:

  1. 通過了Raid與LVM等手段,對數據提供了保護。

  2. 將多塊廉價的硬盤組合起來,成為一個大容量的邏輯盤對外提供服務,提高了容量。

  3. 可以並行寫入,提升讀寫效率。

  4. 很多時候塊存儲采用SAN架構組網,傳輸速率以及封裝協議的原因,使得傳輸速度與讀寫速率得到提升。

缺點:

  1. 采用SAN架構組網時,需要額外為主機購買光纖通道卡,還要買光纖交換機,成本高。

  2. 主機之間的數據無法共享。不利於不同操作系統主機間的數據共享。


文件存儲

典型設備:FTP、NFS服務器

為了克服塊存儲中文件服務共享的問題,所以有了文件存儲。

主機A可以直接對文件存儲進行文件的上傳下載,與塊存儲不同,主機A是不需要再對文件存儲進行格式化的,因為文件管理功能已經由文件存儲自己搞定了。

優點:

  • 造價低:隨便一台機器,普通以太網就可以,不需要SAN網絡。

  • 方便文件共享:針對塊存儲中文件無法共享問題,使用文件存儲,第三方進行中轉。

缺點:

  • 讀寫速率低,傳輸速率慢:以太網,上傳下載速度較慢;另外所有讀寫都要1台服務器里面的硬盤來承擔,相比起磁盤陣列動不動就幾十上百塊硬盤同時讀寫,速率慢了許多。

對象存儲

典型設備:內置大容量硬盤的分布式服務器

對象存儲最常用的方案,就是多台服務器內置大容量硬盤,再裝上對象存儲軟件,然后搞幾台服務器作為管理節點,安裝上對象存儲管理軟件。管理節點可以管理其他服務器對外提供讀寫訪問功能。

塊存儲讀寫快,不利於共享,文件存儲讀寫慢,利於共享。能否搞一個讀寫快,利於共享的出來呢?於是有了對象存儲。對象存儲結合了塊存儲與文件存儲的優點。

對象存儲中,OSD(Object-based Storage Device)是對象存儲設備,MDS(Metadata Server)是元數據服務器。

對象存儲的原理

首先,一個文件包含了屬性(術語叫metadata,元數據,例如該文件的大小、修改時間、存儲路徑等)以及內容(以下簡稱數據)。

以往像FAT32這種文件系統,是直接將一份文件的數據與metadata一起存儲的,存儲過程先將文件按照文件系統的最小塊大小來打散(如4M的文件,假設文件系統要求一個塊4K,那么就將文件打散成1000個小塊),再寫進硬盤里面,過程中沒有區分數據/metadata的。而每個塊最后會告知你下一個要讀取的塊的地址,然后一直這樣順序地按圖索驥,最后完成整份文件的所有塊的讀取。

對象存儲將元數據獨立出來,控制節點叫元數據服務器(服務器+對象存儲管理軟件),里面主要負責存儲對象的屬性(主要是對象的數據被打散存放到了那幾台分布式服務器中的信息),而其他負責存儲數據的分布式服務器叫做OSD,主要負責存儲文件的數據部分。當用戶訪問對象,會先訪問元數據服務器,元數據服務器只負責反饋對象存儲在那些OSD,假設反饋文件A存儲在B、C、D三台OSD,那么用戶就會再次直接訪問3台OSD服務器去讀取數據。

這時候由於是3台OSD同時對外傳輸數據,所以傳輸的速度就加快了。當OSD服務器數量越多,這種讀寫速度的提升就越大,通過這種方式,實現了讀寫快的目的。

另一方面,對象存儲軟件是有專門的文件系統的,所以OSD對象又相當於文件服務器,那么就不存在文件共享方面的困難了,也就解決了文件共享方面的問題。


總結

  • 塊存儲可以認為是裸盤,最多包一層邏輯卷(LVM);常見的DAS、FC-SAN、IP-SAN都是塊存儲,塊存儲最明顯的特征就是不能被操作系統直接讀寫,需要格式化為指定的文件系統(Ext3、Ext4、NTFS)后才可以訪問。優點:讀寫快(帶寬&IOPS);缺點:因為太底層了,不利於擴展。

  • 文件存儲:指的是在文件系統上的存儲,也就是主機操作系統中的文件系統。

  • 對象存儲,對象存儲肯定是分布式存儲,但分布式存儲可能是分布式文件系統,不一定是對象存儲;常見的對象存儲開源實現有 Ceph 的RADOS、openstack的swift、AWS s3等,常見分布式文件系統,lustre、glusterfs、HDFS等;對象存儲和分布式文件系統的表面區別:對象存儲支持的訪問接口基本都是restful接口、而分布式文件系統提供的POSIX兼容的文件操作接口;

分布式文件系統和對象存儲最本質的區別

分布式文件系統文件組織方式為目錄樹、對象存儲采用的則是扁平的組織方式;對象存儲不支持隨機讀取和寫入,put和get操作都是針對的整個文件。


Ceph 簡介

Ceph 獨一無二地在一個統一的系統中同時提供了對象、塊、和文件存儲功能

它可靠性高、管理簡單,並且是開源軟件。 Ceph 的強大可以改變您公司的 IT 基礎架構和海量數據管理能力。

Ceph 可提供極大的伸縮性——供成千用戶訪問 PB 乃至 EB 級的數據。 Ceph 節點以普通硬件和智能守護進程作為支撐點, Ceph 存儲集群組織起了大量節點,它們之間靠相互通訊來復制數據、並動態地重分布數據。

Ceph 官方文檔

Ceph 中文文檔

CEPH 對象存儲

  • REST 風格的接口
  • 與 S3 和 Swift 兼容的 API
  • S3 風格的子域
  • 統一的 S3/Swift 命名空間
  • 用戶管理
  • 利用率跟蹤
  • 條帶化對象
  • 雲解決方案集成
  • 多站點部署
  • 災難恢復

CEPH 塊設備

  • 瘦接口支持
  • 映像尺寸最大 16EB
  • 條帶化可定制
  • 內存緩存
  • 快照
  • 寫時復制克隆
  • 支持內核級驅動
  • 支持 KVM 和 libvirt
  • 可作為雲解決方案的后端
  • 增量備份

CEPH 文件系統

  • 與 POSIX 兼容的語義
  • 元數據獨立於數據
  • 動態重均衡
  • 子目錄快照
  • 可配置的條帶化
  • 有內核驅動支持
  • 有用戶空間驅動支持
  • 可作為 NFS/CIFS 部署
  • 可用於 Hadoop (取代 HDFS)

Ceph 特點

高性能

  • 摒棄了傳統的集中式存儲元數據尋址的方案,采用CRUSH算法,數據分布均衡,並行度高。
  • 考慮了容災域的隔離,能夠實現各類負載的副本放置規則,例如跨機房、機架感知等。
  • 能夠支持上千個存儲節點的規模,支持TB到PB級的數據。

高可用性

  • 副本數可以靈活控制。
  • 支持故障域分隔,數據強一致性。
  • 多種故障場景自動進行修復自愈。
  • 沒有單點故障,自動管理。

高可擴展性

  • 去中心化。
  • 擴展靈活。
  • 隨着節點增加而線性增長。

特性豐富

  • 支持三種存儲接口:塊存儲、文件存儲、對象存儲。
  • 支持自定義接口,支持多種語言驅動。

Ceph 體系結構

stack

stack - 中文

img


Ceph 基礎組件

構成 ceph 集群的基礎組件:OSD、Manager、MDS、Monitor。

  • OSD(ceph-osd):object storage daemon,對象存儲進程。ceph 管理物理硬盤時,引入了OSD概念,每一塊盤都會針對的運行一個OSD進程。換句話說,ceph 集群通過管理 OSD 來管理物理硬盤。OSD 一般功能為:存儲數據、維護數據副本、數據恢復、數據再平衡以及對ceph monitor組件提供相關監控信息。

  • Manager(ceph-mgr):用於收集ceph集群狀態、運行指標,比如存儲利用率、當前性能指標和系統負載。對外提供 ceph dashboard(ceph ui)和 resetful api。Manager組件開啟高可用時,至少2個。

  • Monitor(ceph-mon):維護集群的狀態,包含monitor組件信息,manger 組件信息,osd組件信息,mds組件信息,crush 算法信息。還負責ceph集群的身份驗證功能,client在連接ceph集群時通過此組件進行驗證。Monitor組件開啟高可用時,至少3個。

  • MDS(ceph-mds):Metadata server,元數據服務。為ceph 文件系統提供元數據服務(ceph 對象存儲和塊存儲不需要MDS)。為 posix 文件系統用戶提供性能良好的基礎命令(ls,find等)。


創建Ceph 存儲,至少需要以下服務:

  1. 一個Ceph Monitor
  2. 兩個OSD守護進程

img


Ceph IO算法流程

img

File是用戶需要讀寫的文件。File->Object映射:

  • ino (File的元數據,File的唯一id)。
  • ono(File切分產生的某個object的序號,默認以4M切分一個塊大小)。
  • oid(object id: ino + ono)。

Object是RADOS需要的對象。Ceph指定一個靜態hash函數計算oid的值,將oid映射成一個近似均勻分布的偽隨機值,然后和mask按位相與,得到pgid。Object->PG映射:

  • hash(oid) & mask-> pgid 。
  • mask = PG總數m(m為2的整數冪)-1 。

PG(Placement Group)用於對object的存儲進行組織和位置映射, (類似於redis cluster里面的slot的概念) 一個PG里面會有很多object。采用CRUSH算法,將pgid代入其中,然后得到一組OSD。PG->OSD映射:

  • CRUSH(pgid)->(osd1,osd2,osd3) 。

OSD(Object Storage Device)對象存儲設備:物理或邏輯存儲單元(如LUN)。有時,Ceph用戶使用術語“OSD”來指代Ceph OSD守護進程,盡管正確的術語是“Ceph OSD”。


Ceph IO偽代碼流程

locator = object_name
obj_hash =  hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg)  # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]

參考文檔:


部署Ceph集群

Ceph 集群架構

使用ceph-deploy部署nautilus版Ceph

  • 3個Ceph Monitor
  • 3個Ceph OSD

image-20201210164254751

環境准備

主機名 IP 配置
ceph01 10.0.0.14 1核1G,額外硬盤sdb單個文件50G
ceph02 10.0.0.15 1核1G,額外硬盤sdb單個文件50G
ceph03 10.0.0.16 1核1G,額外硬盤sdb單個文件50G
  • 關閉:selinuxfirewalldNetworkManagerpostfix(非必須)

  • 修改IP地址、主機名

hostnamectl set-hostname 主機名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
  • 添加hosts解析
cat >> /etc/hosts <<EOF
10.0.0.14 ceph01
10.0.0.15 ceph02
10.0.0.16 ceph03
EOF
  • 如果熱添加硬盤,需要掃描發現硬盤
echo '- - -' >/sys/class/scsi_host/host0/scan
echo '- - -' >/sys/class/scsi_host/host1/scan
echo '- - -' >/sys/class/scsi_host/host2/scan
fdisk -l
  • 准備yum源:Base epel ceph
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0

[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF

如果你想保留rpm的話,可以開啟緩存。

vim /etc/yum.conf
... ...
keepcache=1 # 開啟緩存
... ...

打包緩存

mkdir ceph_rpm
find /var/cache/yum -type f -name "*.rpm" | xargs mv -t ceph_rpm
tar zcf ceph_rpm.tar.gz ceph_rpm

ceph-deploy節點

  1. 配置ssh密鑰免密登錄所有節點
ssh-keygen
ssh-copy-id root@ceph01
ssh-copy-id root@ceph02
ssh-copy-id root@ceph03

注意: 如果SSH不使用默認22端口時

cat > ~/.ssh/config <<EOF
Port 12345
EOF
  1. 安裝ceph-deploy
yum install ceph-deploy -y

所有節點安裝

yum install ceph ceph-mon ceph-mgr ceph-radosgw.x86_64 ceph-mds.x86_64 ceph-osd.x86_64 -y

ceph-deploy使用其內置官網源安裝,非常慢!!!因此要提前裝好所需包。


ceph-deploy部署ceph集群

  1. ceph-deploy初始化集群配置文件
cd /root
mkdir ceph-deploy && cd ceph-deploy
ceph-deploy new --public-network 10.0.0.0/24 ceph01 ceph02 ceph03

默認[--cluster-network CLUSTER_NETWORK]=[--public-network PUBLIC_NETWORK]

生產中建議--cluster-network使用萬兆帶寬網絡。

  1. 初始化集群:部署ceph-monitor並啟動
ceph-deploy mon create-initial

在各節點生成配置文件/etc/ceph

  1. 創建管理員用戶:生成並推送管理員密鑰
ceph-deploy admin ceph01 ceph02 ceph03
  1. 查看集群狀態:mon存在
ceph -s
  1. 部署ceph-manager並啟動
ceph-deploy mgr create ceph01 ceph02 ceph03
  1. 查看集群狀態:mon和mgr存在
ceph -s
  1. 創建osd
ceph-deploy osd create ceph01 --data /dev/sdb
ceph-deploy osd create ceph02 --data /dev/sdb
ceph-deploy osd create ceph03 --data /dev/sdb

data:數據盤路徑

journal:日志盤路徑,日志盤(ssd)越快,ceph越快。尤其是小塊數據I/O,提速明顯。

  1. 查看集群狀態:mon和mgr和osd存在
ceph -s

如果狀態有健康警告如下:

[root@ceph01 ceph-deploy]# ceph -s
cluster:
id:     a4f16e95-ba09-49f5-b0bf-ada31833a457
health: HEALTH_WARN
   clock skew detected on mon.ceph03

services:
mon: 3 daemons, quorum ceph01,ceph02,ceph03 (age 23m)
mgr: ceph01(active, since 53m), standbys: ceph02, ceph03
osd: 3 osds: 3 up (since 29m), 3 in (since 29m)

data:
pools:   0 pools, 0 pgs
objects: 0 objects, 0 B
usage:   3.0 GiB used, 147 GiB / 150 GiB avail
pgs:

生產環境請使用ntp服務


測試環境可以調整ceph配置中的[global]下時間偏差閾值:

cat >> /root/ceph-deploy/ceph.conf <<EOF
mon clock drift allowed = 2
mon clock drift warn backoff = 30
EOF

向所有同步的mon節點推送配置文件,重啟mon服務:

ceph-deploy --overwrite-conf config push ceph0{1,2,3}
systemctl restart ceph-mon.target

最后查看集群狀態:HEALTH_OK

  1. 查看monitors信息
ceph mon dump

ceph 資源配置

  1. 創建pool資源池
ceph osd pool create k8s 128 128
  1. 查看pool資源池
ceph osd pool ls
ceph osd pool stats k8s
  1. 調整pool資源池的ps數量
ceph osd pool set k8s pg_num 128
  1. 創建RBD塊設備
rbd create --size 1024 k8s/tomcat_mysql.img
  1. 查看RBD塊設備
rbd info k8s/tomcat_mysql.img
rbd info --pool k8s tomcat_mysql.img
rbd info --pool k8s --image tomcat_mysql.img
  1. 查看OSD節點數量
ceph osd pool get k8s size

增加OSD節點會自動進行數據整合,請在業務低谷期間增加,一台一台慢慢加。

  1. 查看RBD塊設備所有對象
rados -p k8s ls
rados -p k8s ls | grep rbd_data.ac74b202ed1a
rados -p k8s ls | grep rbd_data.ac74b202ed1a | wc -l

用多少,分多少。

  1. 樹狀顯示所有OSD
ceph osd tree

使用RBD塊設備

  1. 禁用高級特性
rbd feature disable k8s/tomcat_mysql.img object-map fast-diff deep-flatten
  1. 映射到實際設備
rbd map k8s/tomcat_mysql.img

關機映射失效,需要重新映射,數據不會丟失。

  1. 格式化
mkfs.xfs /dev/rbd0
  1. 掛載
mount /dev/rbd0 /mnt
  1. 卸載
umount /mnt
  1. 擴容
rbd resize --size 2048 k8s/tomcat_mysql.img
  1. 掛載
mount /dev/rbd0 /mnt
  1. 調整容量
xfs_growfs /dev/rbd0
  1. 掛載,查看
df -Th

Ceph 對接 k8s

Ceph RBD 對接 k8s :參考官方文檔


准備

所有k8s node節點安裝ceph-common

cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0

[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF
yum -y install ceph-common

ceph01

  1. 推送ceph用戶密鑰文件和配置文件給所有k8s node節點
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.13:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.13:/etc/ceph/
  1. 獲取base64加密的ceph用戶key
grep key /etc/ceph/ceph.client.admin.keyring |awk '{printf "%s", $NF}'|base64
  1. 創建最小特性鏡像
rbd create --size 2048 --image-feature layering k8s/test.img
rbd ls -p k8s

k8s-master

  1. master節點編寫Secret資源yaml
mkdir -p /root/k8s_yaml/ceph && cd /root/k8s_yaml/ceph
cat > /root/k8s_yaml/ceph/ceph-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  namespace: tomcat
  name: ceph-secret
type: "kubernetes.io/rbd"
data:
  key: QVFDYTV0RmY3ZVBlQWhBQU45aU1ONHFYdUhNNkRGZ2pCOTJMUFE9PQ==
EOF
  1. master節點創建Secret資源
kubectl create namespace tomcat
kubectl create -f ceph-secret.yaml
  1. master節點查看Secret資源
kubectl get secret -n tomcat
  1. master節點查看Secret資源配置文件
kubectl get secret -n tomcat ceph-secret -o yaml

能看到ceph用戶key,可以解密。


pod 對接ceph rbs存儲

查看解釋

kubectl explain pod.spec.volumes.rbd
  1. master節點編寫Pod資源yaml
cat > /root/k8s_yaml/ceph/test_ceph_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  namespace: tomcat
  name: rbd
spec:
  containers:
    - image: 10.0.0.11:5000/nginx:1.13
      name: rbd-rw
      volumeMounts:
      - name: rbdpd
        mountPath: /data
  volumes:
    - name: rbdpd
      rbd:
        monitors:
        - '10.0.0.14:6789'
        - '10.0.0.15:6789'
        - '10.0.0.16:6789'
        pool: k8s
        image: test.img
        fsType: ext4
        user: admin
        keyring: /etc/ceph/keyring
        secretRef:
          name: ceph-secret
EOF
  1. master節點創建Pod資源
kubectl create -f test_ceph_pod.yaml
  1. master節點查看Pod資源
kubectl get pod -o wide -n tomcat
  1. master節點進入容器,查看有/dev/rbd0設備,驗證對接成功
kubectl exec -n tomcat -it rbd /bin/bash
df -h
  1. node節點查看所有映射的rbd
rbd device ls

pv 對接ceph rbs存儲

  1. master節點編寫PV資源yaml
cat > /root/k8s_yaml/ceph/ceph_pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: ceph01
  labels:
    type: rbd
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  rbd:
    monitors:
    - '10.0.0.14:6789'
    - '10.0.0.15:6789'
    - '10.0.0.16:6789'
    pool: k8s
    image: test2.img
    fsType: xfs
    user: admin
    secretRef:
      name: ceph-secret
EOF

注意:請使用xfs格式。

ext4格式默認創建一個lost+found目錄,導致mysql無法啟動。

  • 需要手動刪除

    df -Th|grep rbd
    rm -fr /var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/k8s-image-test2.img/*
    
  • 或者使用initContainer配置項,參考文檔

  1. ceph創建最小特性鏡像
rbd create --size 2048 --image-feature layering k8s/test2.img
rbd ls -p k8s
  1. master節點創建pv資源
kubectl create -f ceph_pv1.yaml
  1. master節點查看pv資源
kubectl get pv -o wide
  1. master節點編寫PVC資源yaml
cat > /root/k8s_yaml/ceph/ceph_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: tomcat-rbd1
  namespace: tomcat
spec:
  selector:
    matchLabels:
      type: rbd
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
EOF
  1. master節點創建pvc資源
kubectl create -f ceph_pvc.yaml
  1. master節點查看pvc資源
kubectl get pvc -n tomcat -o wide
  1. master節點編寫Deployment資源yaml
cat > /root/k8s_yaml/ceph/mysql-deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: tomcat
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
      - name: mysql
        persistentVolumeClaim:
          claimName: tomcat-rbd1
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master節點創建Deployment資源
kubectl create -f mysql-deploy.yaml
  1. master節點查看Deployment資源
kubectl get pod -n tomcat -o wide

Jenkins實現k8s持續更新

環境准備

主機名 IP 服務 內存
k8s-master 10.0.0.11 kube-apiserver 8080 1G
k8s-node-1 10.0.0.12 kube-apiserver 8080 1G
k8s-node-2 10.0.0.13 Jenkins(tomcat + jdk) 8080 2G
  • 代碼倉庫使用gitee托管

image-20201211160845138


gitee倉庫准備

  1. 創建遠程倉庫

image-20201211112433786

  1. Git 全局設置:
git config --global user.name "卜算子"
git config --global user.email "wuqi83417883@163.com"
  • 新倉庫:
mkdir oldboy
cd oldboy
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/busuanzi/oldboy.git
git push -u origin master
  • 已有倉庫:
cd /opt
git clone https://gitee.com/kangjie1209/monitor.git
git remote remove origin
git remote add origin https://gitee.com/busuanzi/oldboy.git
git push -u origin master

jenkins部署(k8s-node-2)

  1. 准備Jenkins + tomcat + jdk
cd /opt
for n in apache-tomcat-8.0.27.tar.gz jdk-8u102-linux-x64.rpm jenkin-data.tar.gz jenkins.war;do wget http://192.168.15.253/k8s_jenkins/$n ;done
  1. 二進制安裝jenkins
rpm -ivh jdk-8u102-linux-x64.rpm 
mkdir /app -p
tar xf apache-tomcat-8.0.27.tar.gz -C /app
rm -fr /app/apache-tomcat-8.0.27/webapps/*
mv jenkins.war /app/apache-tomcat-8.0.27/webapps/ROOT.war
tar xf jenkin-data.tar.gz -C /root
/app/apache-tomcat-8.0.27/bin/startup.sh 
netstat -lntup

jenkins構建測試

  1. 訪問jenkins:http://10.0.0.12:8080/,默認賬號密碼 admin:123456
  2. 創建一個新任務

image-20201211120409267

  1. 配置jenkins拉取gitlab代碼憑據

image-20201211120743488

image-20201211120622384

  1. 構建Shell測試

image-20201211121051759

  1. 立即構建

image-20201211121150223

  1. 查看控制台輸出

image-20201211121329046


構建docker鏡像

  1. docker鏡像基礎包:nginx:1.13

  2. 編寫dockerfile.dockerignore並運行測試

cat > dockerfile <<EOF
FROM 10.0.0.11:5000/nginx:1.13
RUN rm -rf /usr/share/nginx/html/*
ADD . /usr/share/nginx/html
EOF
echo dockerfile > .dockerignore
docker build -t test:v1 .
docker run -d -p 80:80 test:v1
  1. 瀏覽器訪問http://10.0.0.12/

  2. 上傳dockerfile.dockerignore到私有倉庫

git add .dockerignore dockerfile
git commit -m "add dockerfile"
git push -u origin master
  1. gitee添加標簽v1,修改首頁,添加標簽v2
  2. master節點手動發布
kubectl create namespace oldboy
kubectl run -n oldboy oldboy --image=10.0.0.11:5000/oldboy:v1 --replicas=2
kubectl expose -n oldboy deploy oldboy --type=NodePort --port=80 --target-port=80
kubectl get all -n oldboy

jenkins滾動更新

  1. 使用參數構建

image-20201211150942890

  1. 修改Shell
docker build -t 10.0.0.11:5000/oldboy:$version .
docker push 10.0.0.11:5000/oldboy:$version
kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version

image-20201211152147688

  1. 執行測試

Build with Parameters --> 輸入版本 --> 開始構建

jenkins從gitee下載代碼,構建docker鏡像並上傳到私有倉庫,調用k8s滾動發布。

  1. 查看控制台輸出

image-20201211151931346

  1. shell腳本
if [ -f /tmp/oldboy.lock ];then
    docker build -t 10.0.0.11:5000/oldboy:v$version .
    docker push 10.0.0.11:5000/oldboy:v$version
    kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:v$version
    port=`kubectl -s 10.0.0.11:8080  get svc -n oldboy|grep -oP '(?<=80:)\d+'`
    echo "你的項目地址訪問是http://10.0.0.13:$port"
    echo "更新成功"
else
    docker build -t 10.0.0.11:5000/oldboy:v$version  .
    docker push 10.0.0.11:5000/oldboy:v$version
    kubectl -s 10.0.0.11:8080 create namespace oldboy
    kubectl -s 10.0.0.11:8080 run oldboy -n oldboy  --image=10.0.0.11:5000/oldboy:v$version --replicas=3 --record
    kubectl -s 10.0.0.11:8080 expose -n oldboy deployment oldboy --port=80 --type=NodePort
    port=`kubectl -s 10.0.0.11:8080  get svc -n oldboy|grep -oP '(?<=80:)\d+'`
    echo "你的項目地址訪問是http://10.0.0.13:$port"
    echo "發布成功"
    touch /tmp/oldboy.lock
    chattr +i /tmp/oldboy.lock
fi

jenkins一鍵回滾

另建一個工程,不需要拉代碼,僅僅需要指定版本參數和shell,參數化回滾:

kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version

k8s高可用

架構

image-20201211174520119

主機名 IP 服務
k8s-master01 10.0.0.11 api-server,controller-manager,scheduler,etcd,keepalived,flannel
k8s-master02 10.0.0.12 api-server,controller-manager,scheduler,etcd,keepalived,flannel
k8s-node-1 10.0.0.13 kubernetes-node,flannel

etcd高可用集群

不能單機擴集群,首次使用請使用集群,集群是奇數個,競選。(虛擬機請還原快照)

  1. 所有節點安裝
yum install etcd -y
  1. 所有節點配置
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"  # 節點的名字
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380" # 節點同步數據的地址
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"       # 節點提供服務的地址
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"               # 初始化集群
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"  # 初始化集群令牌
ETCD_INITIAL_CLUSTER_STATE="new"           # 初始化集群狀態
cat > /etc/etcd/etcd.conf <<EOF
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#ETCD_ENABLE_V2="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
EOF
# node2
sed -i "9c ETCD_NAME=\"node2\"" /etc/etcd/etcd.conf
sed -i "20c ETCD_INITIAL_ADVERTISE_PEER_URLS=\"http://10.0.0.12:2380\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.12:2379\"" /etc/etcd/etcd.conf
# node3
sed -i "9c ETCD_NAME=\"node3\"" /etc/etcd/etcd.conf
sed -i "20c ETCD_INITIAL_ADVERTISE_PEER_URLS=\"http://10.0.0.13:2380\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.13:2379\"" /etc/etcd/etcd.conf
  1. 所有節點同時啟動,並加入開機自啟
systemctl enable etcd
systemctl start etcd
  1. 檢查集群健康狀態和成員列表
etcdctl cluster-health
etcdctl member list

flannel配置

  1. 修改配置文件
sed -i "4c FLANNEL_ETCD_ENDPOINTS="http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379"" /etc/sysconfig/flanneld
  1. 創建key
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'
  1. 啟動並加入開機自啟
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker
  1. 檢查網卡
ip a

master節點

master01和master02部署api-server,controller-manager,scheduler

  1. 安裝
yum install kubernetes-master -y
  1. 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://127.0.0.1:8080\"" /etc/kubernetes/config
  1. 啟動並加入開機啟動
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl start kube-scheduler.service
  1. 檢查服務是否安裝正常
kubectl get componentstatus

Keepalived配置

在master01和master02安裝keepalived。

  1. 安裝
yum install keepalived -y
  1. master01配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL_11
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.10
    }
}
EOF
  1. master02配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL_12
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.10
    }
}
EOF
  1. 啟動並加入開機自啟
systemctl enable keepalived
systemctl start keepalived

node節點

所有node節點的kubelet,kube-proxy指向api-server的vip。

  1. 安裝:見k8s集群yum安裝
  2. 配置
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.10:8080\"" /etc/kubernetes/config
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.10:8080\"" /etc/kubernetes/kubelet
  1. 重啟生效
systemctl restart kubelet.service kube-proxy.service


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM