k8s部署
k8s中容器的管理方式
?
Kubernetes集群創建方式
centainerd
默認情況下,K8S在創建集群時使用的方式
docker
docker使用的普記錄最高,雖然K8S在1.24版本后已經費力了kubelet對docker的支持,但時可以借助cri-docker方式來實現集群創建
cri-o
CRI-O的方式是Kubernetes創建容器最直接的一種方式,在創建集群的時候,需要借助于cri-o插件的方式來實現Kubernetes集群的創建
[!NOTE]
docker 和cri-o 這兩種方式要對kubelet程序的啟動參數進行設置
K8s–harbor主機
# 以下火墻及selinux每個主機都得關
[root@docker-harbor ~]# systemctl disable --now firewalld
Removed "/etc/systemd/system/multi-user.target.wants/firewalld.service".
Removed "/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service".
[root@docker-harbor ~]# getenforce
Disabled[root@docker-harbor ~]# cd /etc/yum.repos.d
[root@docker-harbor yum.repos.d]# vim docker.repo
[root@docker-harbor yum.repos.d]# cat docker.repo
[docker]
name = docker-ce
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
gpgcheck = 0[root@docker-harbor yum.repos.d]# yum makecache
[root@docker-harbor yum.repos.d]# rpm -qa | grep podman
podman-4.6.1-5.el9.x86_64
cockpit-podman-76-1.el9_3.noarch[root@docker-harbor yum.repos.d]# rm -rf podman-4.6.1-5.el9.x86_64
[root@docker-harbor yum.repos.d]# rm -rf cockpit-podman-76-1.el9_3.noarch# 上傳所需文件
[root@docker-harbor ~]# cd /mnt/
[root@docker-harbor mnt]# ls
docker.tar.gz ?packages.zip[root@docker-harbor mnt]# tar zxf docker.tar.gz
[root@docker-harbor mnt]# unzip packages.zip[root@docker-harbor mnt]# ls
docker ?docker.tar.gz packages ?packages.zip
[root@docker-harbor mnt]# cd docker/[root@docker-harbor docker]# yum install *.rpm -y
# 在第15行命令,在后面加上參數 --iptables=true
[root@docker-harbor docker]# vim /usr/lib/systemd/system/docker.service
15 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true[root@docker-harbor docker]# systemctl daemon-reload
[root@docker-harbor docker]# systemctl restart docker
?
[root@docker-harbor docker]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@docker-harbor docker]# sysctl -p
net.ipv4.ip_forward = 1[root@docker-harbor docker]# systemctl ?enable --now docker
[root@docker-harbor docker]# docker info
?
# 以下除了rhel9不需要做,其他版本的系統建議去做
# 激活內核網絡選項
]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
]# modprobe br_netfilter
]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1]# sysctl --system
]# systemctl ?restart docker
?
# 創建了證書與密鑰
[root@docker-harbor ~]# mkdir -p /data/certs
[root@docker-harbor ~]# ?openssl req -newkey ?rsa:4096 \
-nodes -sha256 -keyout /data/certs/dhj.org.key \
-addext "subjectAltName = DNS:reg.dhj.org" \
-x509 -days 365 -out /data/certs/dhj.org.crtCommon Name (eg, your name or your server's hostname) []:reg.dhj.org
# 創建證書目錄并部署信任證書(使Docker客戶端信任私有倉庫的HTTPS證書)
[root@docker-harbor ~]# mkdir /etc/docker/certs.d/reg.dhj.org/ -p
[root@docker-harbor ~]# cp /data/certs/dhj.org.crt ?/etc/docker/certs.d/reg.dhj.org/ca.crt
[root@docker-harbor ~]# systemctl restart docker
?
[root@docker-harbor ~]# cd /mnt/packages/
[root@docker-harbor packages]# cp -p harbor-offline-installer-v2.5.4.tgz ?/root[root@docker-harbor packages]# cd
[root@docker-harbor ~]# tar zxf harbor-offline-installer-v2.5.4.tgz[root@docker-harbor ~]# cd harbor
[root@docker-harbor harbor]# cp harbor.yml.tmpl harbor.yml# 需要修改內容如下(如果一致,不變即可):
[root@docker-harbor harbor]# vim harbor.yml
? 5 hostname: reg.dhj.org
?17 ? certificate: /data/certs/dhj.org.crt?? ??? ??? ??? ?# 看自己的存放位置
?18 ? private_key: /data/certs/dhj.org.key?? ??? ??? ??? ?# 看自己的存放位置
?34 harbor_admin_password: admin?? ??? ??? ??? ??? ??? ?# 初始密碼
?47 data_volume: /data?? ??? ??? ??? ??? ??? ??? ??? ??? ?# 此處掛載的目錄(需要跟上面證書與密鑰在一個目錄下)
[root@docker-harbor harbor]# ./install.sh --with-chartmuseum
[root@docker-harbor harbor]# docker compose stop
[root@docker-harbor harbor]# docker compose up -d
?
# 去瀏覽器中去測試172.25.254.200
?
[root@docker-harbor ~]# cd /etc/docker/
[root@docker-harbor docker]# vim daemon.json
[root@docker-harbor docker]# cat daemon.json
{
? ? ? ? "registry-mirrors": ["https://reg.dhj.org"]
}[root@docker-harbor docker]# systemctl restart docker
[root@k8s-harbor ~]# cd harbor/
[root@k8s-harbor harbor]# docker compose up -d[root@docker-harbor harbor]# docker login reg.dhj.org
Username: admin
Password:admin
?
集群環境初始化
所有k8s集群節點執行以下步驟
關閉火墻及SELinux
所有禁用swap和本地解析
]# vim /etc/fstab
UUID=5b62292e-603b-467a-a1ad-160d612e6f81 / ? ? ? ? ? ? ? ? ? ? ? xfs ? ? defaults ? ? ? ?0 0
UUID=31c1cd5c-22a7-42e8-91d1-f36d1bc1edaa /boot ? ? ? ? ? ? ? ? ? xfs ? ? defaults ? ? ? ?0 0
# UUID=51600096-c0fa-4247-8d7f-6a40b6b05300 none ? ? ? ? ? ? ? ? ? ?swap ? ?defaults ? ? ? ?0 0?? ??? ?# 將最后一行注釋掉即可]# systemctl daemon-reload
]# systemctl mask swap.target
]# swapoff -a
]# swapon -s?? ?# 沒有顯示內容即可(不保險的話:可以使用reboot之后,再次 swapon -s 查看)[root@k8s-node1 ~]# vim /etc/hosts
172.25.254.10 ? k8s-node1
172.25.254.20 ? k8s-node2
172.25.254.100 ?k8s-master
172.25.254.200 ?reg.dhj.org# 快速將每臺主機部署
[root@k8s-node1 ~]# scp /etc/hosts root@172.25.254.20:/etc/hosts
[root@k8s-node1 ~]# scp /etc/hosts root@172.25.254.100:/etc/hosts
[root@k8s-node1 ~]# scp /etc/hosts root@172.25.254.200:/etc/hosts
?
所有安裝docke
[root@docker-harbor yum.repos.d]# rpm -qa | grep podman
podman-4.6.1-5.el9.x86_64
cockpit-podman-76-1.el9_3.noarch[root@docker-harbor yum.repos.d]# rm -rf podman-4.6.1-5.el9.x86_64
[root@docker-harbor yum.repos.d]# rm -rf cockpit-podman-76-1.el9_3.noarch
?
# 之前harbor已經安裝就不用管了,其余必須安裝
]# vim /etc/yum.repos.d/docker.repo
[docker]
name=docker
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck=0]# yum makecache
]# dnf install docker-ce -y?? ??? ??? ??? ?# 此處要是不想安裝的話,可以將harbor里面的東西使用scp復制過來即可。# 在第15行命令,在后面加上參數 --iptables=true
]# vim /usr/lib/systemd/system/docker.service
15 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true]# systemctl daemon-reload
]# systemctl restart docker?
?
# 如果不想安裝的話,執行以下命令
[root@reg ~]# cd /mnt/docker/
[root@reg docker]# scp * root@172.25.254.10:/mnt
[root@reg docker]# scp * root@172.25.254.20:/mnt
[root@reg docker]# scp * root@172.25.254.100:/mnt
]# dnf install -y /mnt/*.rpm
[root@k8s-master mnt]# vim /usr/lib/systemd/system/docker.service
15 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true[root@k8s-master mnt]# scp /usr/lib/systemd/system/docker.service root@172.25.254.10:/usr/lib/systemd/system/docker.service
[root@k8s-master mnt]# scp /usr/lib/systemd/system/docker.service root@172.25.254.20:/usr/lib/systemd/system/docker.service]# systemctl daemon-reload
]# systemctl restart docker
?
?所有階段復制harbor倉庫中的證書并啟動docker
]# mkdir /etc/docker/certs.d/reg.dhj.org/ -p
[root@reg ~]# scp /etc/docker/certs.d/reg.dhj.org/ca.crt root@172.25.254.10:/etc/docker/certs.d/reg.dhj.org/ca.crt
[root@reg ~]# scp /etc/docker/certs.d/reg.dhj.org/ca.crt root@172.25.254.20:/etc/docker/certs.d/reg.dhj.org/ca.crt
[root@reg ~]# scp /etc/docker/certs.d/reg.dhj.org/ca.crt root@172.25.254.100:/etc/docker/certs.d/reg.dhj.org/ca.crt
]# systemctl restart docker]# systemctl enable --now docker
# 此時需要將docker作為我們的默認庫
# 編寫主機的鏡像庫的加速節點(這里以master主機為例,編寫好之后進行scp即可)
[root@k8s-master ~]# cd /etc/docker/[root@k8s-master docker]# vim daemon.json
{
? ? ? ? "registry-mirrors": ["https://reg.dhj.org"]
}[root@k8s-master docker]# cd
[root@k8s-master ~]# scp /etc/docker/daemon.json root@172.25.254.10:/etc/docker/daemon.json
[root@k8s-master ~]# scp /etc/docker/daemon.json root@172.25.254.20:/etc/docker/daemon.json]# systemctl restart docker
# 登陸harbor倉庫
]# docker login reg.dhj.org
Username: admin
Password: admin# 登錄上去之后進行測試
]# docker info
?
# 此處要是顯示Error response from daemon: Get "https://reg.dhj.org/v2/": dial tcp 172.25.254.200:443: connect: connection refused
# 可以在harbor主機中執行以下命令然后再次測試即可
[root@reg ~]# cd harbor/
[root@reg harbor]# docker compose stop
[root@reg harbor]# docker compose up -d
?
安裝K8S部署工具
# 部署軟件倉庫,添加K8S源
[root@k8s-master ~]# vim /etc/yum.repos.d/k8s.repo
[k8s]
name=k8s
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm
gpgcheck=0[root@k8s-master ~]# scp /etc/yum.repos.d/k8s.repo root@172.25.254.10:/etc/yum.repos.d/k8s.repo
[root@k8s-master ~]# scp /etc/yum.repos.d/k8s.repo root@172.25.254.20:/etc/yum.repos.d/k8s.repo]# yum makecache
# 安裝軟件
]# dnf install kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0 -y
?
pod管理
高可用性和可靠性:
自動故障恢復:如果一個 Pod 失敗或被刪除,控制器會自動創建新的 Pod 來維持期望的副本數量。確保應用始終處于可用狀態,減少因單個 Pod 故障導致的服務中斷。
健康檢查和自愈:可以配置控制器對 Pod 進行健康檢查(如存活探針和就緒探針)。如果 Pod 不健康,控制器會采取適當的行動,如重啟 Pod 或刪除并重新創建它,以保證應用的正常運行。
可擴展性:
輕松擴縮容:可以通過簡單的命令或配置更改來增加或減少 Pod 的數量,以滿足不同的工作負載需求。例如,在高流量期間可以快速擴展以處理更多請求,在低流量期間可以縮容以節省資源。
水平自動擴縮容(HPA):可以基于自定義指標(如 CPU 利用率、內存使用情況或應用特定的指標)自動調整 Pod 的數量,實現動態的資源分配和成本優化。
版本管理和更新:
滾動更新:對于 Deployment 等控制器,可以執行滾動更新來逐步替換舊版本的 Pod 為新版本,確保應用在更新過程中始終保持可用。可以控制更新的速率和策略,以減少對用戶的影響。
回滾:如果更新出現問題,可以輕松回滾到上一個穩定版本,保證應用的穩定性和可靠性。
聲明式配置:
簡潔的配置方式:使用 YAML 或 JSON 格式的聲明式配置文件來定義應用的部署需求。這種方式使得配置易于理解、維護和版本控制,同時也方便團隊協作。
期望狀態管理:只需要定義應用的期望狀態(如副本數量、容器鏡像等),控制器會自動調整實際狀態與期望狀態保持一致。無需手動管理每個 Pod 的創建和刪除,提高了管理效率。
服務發現和負載均衡:
自動注冊和發現:Kubernetes 中的服務(Service)可以自動發現由控制器管理的 Pod,并將流量路由到它們。這使得應用的服務發現和負載均衡變得簡單和可靠,無需手動配置負載均衡器。
流量分發:可以根據不同的策略(如輪詢、隨機等)將請求分發到不同的 Pod,提高應用的性能和可用性。
多環境一致性:
一致的部署方式:在不同的環境(如開發、測試、生產)中,可以使用相同的控制器和配置來部署應用,確保應用在不同環境中的行為一致。這有助于減少部署差異和錯誤,提高開發和運維效率。
?
# 監控
watch -n1 命令
#建立控制器并自動運行pod
[root@k8s-master ~]# kubectl create deployment timinglee --image nginx
[root@k8s-master ~]# kubectl get pods
NAME ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE
timinglee-859fbf84d6-mrjvx ? 1/1 ? ? Running ? 0 ? ? ? ? ?37m#為timinglee擴容
[root@k8s-master ~]# kubectl scale deployment timinglee --replicas 6
[root@k8s-master ~]# kubectl get pods#為timinglee縮容
root@k8s-master ~]# kubectl scale deployment timinglee --replicas 2
deployment.apps/timinglee scaled
[root@k8s-master ~]# kubectl get pods
NAME ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE
timinglee-859fbf84d6-mrjvx ? 1/1 ? ? Running ? 0 ? ? ? ? ?38m
timinglee-859fbf84d6-tsn97 ? 1/1 ? ? Running ? 0 ? ? ? ? ?73s
?
#建立控制器并自動運行pod
[root@k8s-master ~]# kubectl create deployment timinglee --image nginx
[root@k8s-master ~]# kubectl get pods
NAME ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE
timinglee-859fbf84d6-mrjvx ? 1/1 ? ? Running ? 0 ? ? ? ? ?37m#為timinglee擴容
[root@k8s-master ~]# kubectl scale deployment timinglee --replicas 6
[root@k8s-master ~]# kubectl get pods#為timinglee縮容
root@k8s-master ~]# kubectl scale deployment timinglee --replicas 2
deployment.apps/timinglee scaled
[root@k8s-master ~]# kubectl get pods
NAME ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE
timinglee-859fbf84d6-mrjvx ? 1/1 ? ? Running ? 0 ? ? ? ? ?38m
timinglee-859fbf84d6-tsn97 ? 1/1 ? ? Running ? 0 ? ? ? ? ?73s
?
控制器
控制器也是管理pod的一種手段
自主式pod:pod退出或意外關閉后不會被重新創建
控制器管理的 Pod:在控制器的生命周期里,始終要維持 Pod 的副本數目
Pod控制器是管理pod的中間層,使用Pod控制器之后,只需要告訴Pod控制器,想要多少個什么樣的Pod就可以了,它會創建出滿足條件的Pod并確保每一個Pod資源處于用戶期望的目標狀態。如果Pod資源在運行中出現故障,它會基于指定策略重新編排Pod
當建立控制器后,會把期望值寫入etcd,k8s中的apiserver檢索etcd中我們保存的期望狀態,并對比pod的當前狀態,如果出現差異代碼自驅動立即恢復
deployment控制器示例
# 生成yaml文件
[root@k8s-master ~]# kubectl create deployment deployment --image myapp:v1 ?--dry-run=client -o yaml > deployment.yml[root@k8s-master ~]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? name: deployment
spec:
? replicas: 4
? selector:
? ? matchLabels:
? ? ? app: myapp
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: myapp
? ? spec:
? ? ? containers:
? ? ? - image: myapp:v1
? ? ? ? name: myapp
# 建立pod
[root@k8s-master ~]# kubectl apply -f deployment.yml
deployment.apps/deployment created# 查看pod信息
[root@k8s-master ~]# kubectl get pods --show-labels
NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? LABELS
deployment-5d886954d4-2ckqw ? 1/1 ? ? Running ? 0 ? ? ? ? ?23s ? app=myapp,pod-template-hash=5d886954d4
deployment-5d886954d4-m8gpd ? 1/1 ? ? Running ? 0 ? ? ? ? ?23s ? app=myapp,pod-template-hash=5d886954d4
deployment-5d886954d4-s7pws ? 1/1 ? ? Running ? 0 ? ? ? ? ?23s ? app=myapp,pod-template-hash=5d886954d4
deployment-5d886954d4-wqnvv ? 1/1 ? ? Running ? 0 ? ? ? ? ?23s ? app=myapp,pod-template-hash=5d886954d4
?
[root@k8s-master ~]# kubectl get pods -o wide
NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? ? IP ? ? ? ? ? ?NODE ? ? ? ?NOMINATED NODE ? READINESS GATES
deployment-5d886954d4-2ckqw ? 1/1 ? ? Running ? 0 ? ? ? ? ?2m40s ? 10.244.2.14 ? k8s-node2 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-m8gpd ? 1/1 ? ? Running ? 0 ? ? ? ? ?2m40s ? 10.244.1.17 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-s7pws ? 1/1 ? ? Running ? 0 ? ? ? ? ?2m40s ? 10.244.1.16 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-wqnvv ? 1/1 ? ? Running ? 0 ? ? ? ? ?2m40s ? 10.244.2.15 ? k8s-node2 ? <none> ? ? ? ? ? <none># pod運行容器版本為v1
[root@k8s-master ~]# curl ?10.244.2.14
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>[root@k8s-master ~]# kubectl describe deployments.apps deployment
Name: ? ? ? ? ? ? ? ? ? deployment
Namespace: ? ? ? ? ? ? ?default
CreationTimestamp: ? ? ?Sun, 01 Sep 2024 23:19:10 +0800
Labels: ? ? ? ? ? ? ? ? <none>
Annotations: ? ? ? ? ? ?deployment.kubernetes.io/revision: 1
Selector: ? ? ? ? ? ? ? app=myapp
Replicas: ? ? ? ? ? ? ? 4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType: ? ? ? ? ? RollingUpdate
MinReadySeconds: ? ? ? ?0
RollingUpdateStrategy: ?25% max unavailable, 25% max surge?? ??? ??? ?# 默認每次更新25%
# 更新容器運行版本
[root@k8s-master ~]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? name: deployment
spec:
? minReadySeconds: 5?? ??? ??? ??? ?# 最小就緒時間5秒
? replicas: 4
? selector:
? ? matchLabels:
? ? ? app: myapp? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: myapp
? ? spec:
? ? ? containers:
? ? ? - image: myapp:v2?? ??? ??? ??? ?# 更新為版本2
? ? ? ? name: myapp[root@k8s2 pod]# kubectl apply -f deployment-example.yaml
# 更新過程
[root@k8s-master ~]# watch - n1 kubectl get pods ?-o wide?
NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE
deployment-5d886954d4-8kb28 ? 1/1 ? ? Running ? 0 ? ? ? ? ?48s
deployment-5d886954d4-8s4h8 ? 1/1 ? ? Running ? 0 ? ? ? ? ?49s
deployment-5d886954d4-rclkp ? 1/1 ? ? Running ? 0 ? ? ? ? ?50s
deployment-5d886954d4-tt2hz ? 1/1 ? ? Running ? 0 ? ? ? ? ?50s
deployment-7f4786db9c-g796x ? 0/1 ? ? Pending ? 0 ? ? ? ? ?0s# 測試更新效果
[root@k8s-master ~]# kubectl get pods -o wide
NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? IP ? ? ? ? ? ?NODE ? ? ? ?NOMINATED NODE ? READINESS GATES
deployment-7f4786db9c-967fk ? 1/1 ? ? Running ? 0 ? ? ? ? ?10s ? 10.244.1.26 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-7f4786db9c-cvb9k ? 1/1 ? ? Running ? 0 ? ? ? ? ?10s ? 10.244.2.24 ? k8s-node2 ? <none> ? ? ? ? ? <none>
deployment-7f4786db9c-kgss4 ? 1/1 ? ? Running ? 0 ? ? ? ? ?9s ? ?10.244.1.27 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-7f4786db9c-qts8c ? 1/1 ? ? Running ? 0 ? ? ? ? ?9s ? ?10.244.2.25 ? k8s-node2 ? <none> ? ? ? ? ? <none>[root@k8s-master ~]# curl ?10.244.1.26
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
?
版本回滾
[root@k8s-master ~]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? name: deployment
spec:
? replicas: 4
? selector:
? ? matchLabels:
? ? ? app: myapp? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: myapp
? ? spec:
? ? ? containers:
? ? ? - image: myapp:v1?? ??? ??? ??? ?# 回滾到之前版本
? ? ? ? name: myapp
[root@k8s-master ~]# kubectl apply -f deployment.yml
deployment.apps/deployment configured# 測試回滾效果
[root@k8s-master ~]# kubectl get pods -o wide
NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? IP ? ? ? ? ? ?NODE ? ? ? ?NOMINATED NODE ? READINESS GATES
deployment-5d886954d4-dr74h ? 1/1 ? ? Running ? 0 ? ? ? ? ?8s ? ?10.244.2.26 ? k8s-node2 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-thpf9 ? 1/1 ? ? Running ? 0 ? ? ? ? ?7s ? ?10.244.1.29 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-vmwl9 ? 1/1 ? ? Running ? 0 ? ? ? ? ?8s ? ?10.244.1.28 ? k8s-node1 ? <none> ? ? ? ? ? <none>
deployment-5d886954d4-wprpd ? 1/1 ? ? Running ? 0 ? ? ? ? ?6s ? ?10.244.2.27 ? k8s-node2 ? <none> ? ? ? ? ? <none>[root@k8s-master ~]# curl ?10.244.2.26
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
?
滾動更新策略
[root@k8s-master ~]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? name: deployment
spec:
? minReadySeconds: 5?? ??? ?# 最小就緒時間,指定pod每隔多久更新一次
? replicas: 4
? strategy:?? ??? ??? ??? ??? ?# 指定更新策略
? ? rollingUpdate:
? ? ? maxSurge: 1?? ??? ??? ?# 比定義pod數量多幾個
? ? ? maxUnavailable: 0?? ??? ?# 比定義pod個數少幾個
? selector:
? ? matchLabels:
? ? ? app: myapp? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: myapp
? ? spec:
? ? ? containers:
? ? ? - image: myapp:v1
? ? ? ? name: myapp
[root@k8s2 pod]# kubectl apply -f deployment-example.yaml
?
daemonset 示例
[root@k8s2 pod]# vim daemonset-example.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
? name: daemonset-example
spec:
? selector:
? ? matchLabels:
? ? ? app: nginx
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: nginx
? ? spec:
? ? ? tolerations:?? ??? ?# 對于污點節點的容忍
? ? ? - effect: NoSchedule
? ? ? ? operator: Exists
? ? ? containers:
? ? ? - name: nginx
? ? ? ? image: nginx:1.23[root@k8s-master ~]# kubectl get pods ?-o wide
NAME ? ? ? ? ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? IP ? ? ? ? ? ?NODE ? ? ? ? NOMINATED NODE ? READINESS GATES
daemonset-87h6s ? 1/1 ? ? Running ? 0 ? ? ? ? ?47s ? 10.244.0.8 ? ?k8s-master ? <none> ? ? ? ? ? <none>
daemonset-n4vs4 ? 1/1 ? ? Running ? 0 ? ? ? ? ?47s ? 10.244.2.38 ? k8s-node2 ? ?<none> ? ? ? ? ? <none>
daemonset-vhxmq ? 1/1 ? ? Running ? 0 ? ? ? ? ?47s ? 10.244.1.40 ? k8s-node1 ? ?<none> ? ? ? ? ? <none>
# 回收
[root@k8s2 pod]# kubectl delete -f daemonset-example.yml
?
?job 控制器示例
# 先上傳測試的鏡像
[root@k8s-master mnt]# docker load -i perl-5.34.tar.gz
[root@k8s-master mnt]# docker tag perl:5.34.0 reg.dhj.org/library/perl:5.34.0
[root@k8s-master mnt]# docker push reg.dhj.org/library/perl:5.34.0[root@k8s2 pod]# vim job.yml
apiVersion: batch/v1
kind: Job
metadata:
? name: pi
spec:
? completions: 6?? ??? ?# 一共完成任務數為6?? ??? ?
? parallelism: 2?? ??? ?# 每次并行完成2個
? template:
? ? spec:
? ? ? containers:
? ? ? - name: pi
? ? ? ? image: perl:5.34.0
? ? ? ? command: ["perl", ?"-Mbignum=bpi", "-wle", "print bpi(2000)"]?? ?# 計算Π的后2000位
? ? ? restartPolicy: Never?? ??? ??? ??? ??? ??? ?# 關閉后不自動重啟
? backoffLimit: 4?? ??? ??? ??? ??? ??? ??? ??? ?# 運行失敗后嘗試4重新運行[root@k8s2 pod]# kubectl apply -f job.yml
?
cronjob控制器示例
[root@k8s2 pod]# vim cronjob.yml
apiVersion: batch/v1
kind: CronJob
metadata:
? name: hello
spec:
? schedule: "* * * * *"
? jobTemplate:
? ? spec:
? ? ? template:
? ? ? ? spec:
? ? ? ? ? containers:
? ? ? ? ? - name: hello
? ? ? ? ? ? image: busybox
? ? ? ? ? ? imagePullPolicy: IfNotPresent
? ? ? ? ? ? command:
? ? ? ? ? ? - /bin/sh
? ? ? ? ? ? - -c
? ? ? ? ? ? - date; echo Hello from the Kubernetes cluster
? ? ? ? ? restartPolicy: OnFailure[root@k8s2 pod]# kubectl apply -f cronjob.yml
微服務
用控制器來完成集群的工作負載,需要通過微服務暴漏出去后才能被訪問
?
# 生成控制器文件并建立控制器
[root@k8s-master ~]# kubectl create deployment dhj --image myapp:v1 --replicas 2 --dry-run=client -o yaml > dhj.yml[root@k8s-master ~]# kubectl apply -f dhj.yml
deployment.apps/dhj created# 生成微服務yaml追加到已有yaml中
[root@k8s-master ~]# kubectl expose deployment dhj --port 80 --target-port 80 --dry-run=client -o yaml >> dhj.yml
[root@k8s-master ~]# vim dhj.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? labels:
? ? app: dhj
? name: dhj
spec:
? replicas: 2
? selector:
? ? matchLabels:
? ? ? app: dhj
? template:
? ? metadata:
? ? ? creationTimestamp: null
? ? ? labels:
? ? ? ? app: dhj
? ? spec:
? ? ? containers:
? ? ? - image: myapp:v1
? ? ? ? name: myapp
---?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?# 不同資源間用---隔開apiVersion: v1
kind: Service
metadata:
? labels:
? ? app: dhj
? name: dhj
spec:
? ports:
? - port: 80
? ? protocol: TCP
? ? targetPort: 80
? selector:
? ? app: dhj[root@k8s-master ~]# kubectl apply -f dhj.yml
service/dhj created[root@k8s-master ~]# kubectl get svc
NAME ? ? ? ? TYPE ? ? ? ?CLUSTER-IP ? ? ? EXTERNAL-IP ? PORT(S) ? AGE
dhj ? ? ? ? ?ClusterIP ? 10.97.95.78 ? ? ?<none> ? ? ? ?80/TCP ? ?6s
kubernetes ? ClusterIP ? 10.96.0.1 ? ? ? ?<none> ? ? ? ?443/TCP ? 2d17h
?
微服務默認使用iptables調度
[root@k8s-master ~]# kubectl get services ?-o wide
NAME ? ? ? ? TYPE ? ? ? ?CLUSTER-IP ? ?EXTERNAL-IP ? PORT(S) ? AGE ? ? SELECTOR
dhj ? ? ? ? ?ClusterIP ? 10.97.95.78 ? <none> ? ? ? ?80/TCP ? ?112s ? ?app=dhj?? ??? ??? ?# 集群內部ip為78
kubernetes ? ClusterIP ? 10.96.0.1 ? ? <none> ? ? ? ?443/TCP ? 2d17h ? <none># 可以在火墻中查看到策略信息
[root@k8s-master ~]# iptables -t nat -nL
KUBE-SVC-RV2MKWNOHWTUCXGM ?tcp ?-- ?0.0.0.0/0 ? ? ? ? ? ?10.97.95.78 ? ? ? ? ?/* default/dhj cluster IP */ tcp dpt:80
?
ipvs模式配置方式
在所有節點中安裝ipvsadm
[root@k8s-master & node1 & node2 ~]# yum install ipvsadm -y
修改master節點的代理配置
[root@k8s-master ~]# kubectl -n kube-system edit cm kube-proxy
? ? metricsBindAddress: ""
? ? mode: "ipvs"?? ??? ??? ??? ??? ??? ??? ?#設置kube-proxy使用ipvs模式
? ? nftables:
重啟pod
# 強制重啟Kubernetes集群中kube-system命名空間下的所有kube-proxy Pod
[root@k8s-master ~]# kubectl -n kube-system get ?pods ? | awk '/kube-proxy/{system("kubectl -n kube-system delete pods "$1)}'[root@k8s-master ~]# ipvsadm -Ln
集群儲存
ConfigMap演練
ConfigMap創建方式
[root@k8s-master mnt]# kubectl create cm ceshi --from-literal name1=dhj
[root@k8s-master mnt]# kubectl describe cm ceshi
?
?
使用ConfigMap填充環境變量
[root@k8s-master mnt]# kubectl run testpod --image busyboxplus --dry-run=client -o yaml > test.yml
[root@k8s-master ~]# vim cmcfg1.yml
[root@k8s-master mnt]# kubectl apply -f cmcfg1.yml[root@k8s-master ~]# kubectl create cm cm-ceshi --from-file cmcfg1.yml --dry-run=client
[root@k8s-master ~]# kubectl describe cm cm-ceshi
?
# 將cm中的內容映射為指定變量
[root@k8s-master ~]# vim testyaml1.yml
apiVersion: v1
kind: Pod
metadata:
? labels:
? ? run: testyaml
? name: testyaml
spec:
? containers:
? - image: busyboxplus:latest
? ? name: testyaml
? ? command:
? ? - /bin/sh
? ? - -c
? ? - env
? ? env:
? ? - name: key1
? ? ? valueFrom:
? ? ? ? configMapKeyRef:
? ? ? ? ? name: testyaml
? ? ? ? ? key: db_host
? ? - name: key2
? ? ? valueFrom:
? ? ? ? configMapKeyRef:
? ? ? ? ? name: testyaml
? ? ? ? ? key: db_port
? restartPolicy: Never[root@k8s-master ~]# kubectl apply -f testyaml1.yml
[root@k8s-master mnt]# kubectl create cm testpod --from-file testyaml1.yml
[root@k8s-master mnt]# kubectl logs pod/testyaml | grep key
key1=172.25.254.100
key2=3306
?
?
# 把cm中的值直接映射為變量
[root@k8s-master ~]# vim testpod2.yml
apiVersion: v1
kind: Pod
metadata:
? labels:
? ? run: testpod
? name: testpod
spec:
? containers:
? - image: busyboxplus:latest
? ? name: testpod
? ? command:
? ? - /bin/sh
? ? - -c
? ? - env
? ? envFrom:
? ? - configMapRef:
? ? ? ? name: testpod
? restartPolicy: Never# 查看日志
[root@k8s-master mnt]# kubectl logs pod/testpod | grep db
db_port=3306
db_host=172.25.254.100
?
通過數據卷使用ConfigMap
[root@k8s-master ~]# vim testpod4.yml
apiVersion: v1
kind: Pod
metadata:
? labels:
? ? run: testpod
? name: testpod
spec:
? containers:
? - image: busyboxplus:latest
? ? name: testpod
? ? command:
? ? - /bin/sh
? ? - -c
? ? - cat /config/db_host
? ? volumeMounts:?? ??? ??? ??? ??? ?# 調用卷策略
? ? - name: config-volume?? ??? ??? ?# 卷名稱
? ? ? mountPath: /config
? volumes:?? ??? ??? ??? ??? ??? ??? ?# 聲明卷的配置
? - name: config-volume?? ??? ??? ??? ?# 卷名稱
? ? configMap:
? ? ? name: testpod
? restartPolicy: Never# 查看日志
[root@k8s-master ~]# kubectl logs testpod
172.25.254.100
利用ConfigMap填充pod
# 建立配置文件模板
[root@k8s-master ~]# vim nginx.conf
server {
? listen 8000;
? server_name _;
? root /usr/share/nginx/html;
? index index.html;
}# 利用模板生成cm
root@k8s-master ~]# kubectl create cm nginx-conf --from-file nginx.conf
configmap/nginx-conf created
[root@k8s-master ~]# kubectl describe cm nginx-conf
Name: ? ? ? ? nginx-conf
Namespace: ? ?default
Labels: ? ? ? <none>
Annotations: ?<none>Data
====
nginx.conf:
----
server {
? listen 8000;
? server_name _;
? root /usr/share/nginx/html;
? index index.html;
}
BinaryData
====Events: ?<none>
# 建立nginx控制器文件
[root@k8s-master ~]# kubectl create deployment nginx --image nginx:latest --replicas 1 --dry-run=client -o yaml > nginx.yml# 設定nginx.yml中的卷
[root@k8s-master ~]# vim nginx.yml
[root@k8s-master ~]# cat nginx.
cat: nginx.: 沒有那個文件或目錄
[root@k8s-master ~]# cat nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
? labels:
? ? app: nginx
? name: nginx
spec:
? replicas: 1
? selector:
? ? matchLabels:
? ? ? app: nginx
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: nginx
? ? spec:
? ? ? containers:
? ? ? - image: nginx:latest
? ? ? ? name: nginx
? ? ? ? volumeMounts:
? ? ? ? - name: config-volume
? ? ? ? ? mountPath: /etc/nginx/conf.d? ? ? volumes:
? ? ? ? - name: config-volume
? ? ? ? ? configMap:
? ? ? ? ? ? name: nginx-conf
# 測試
[root@k8s-master ~]# kubectl get pods -o wide
NAME ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ?RESTARTS ? AGE ? ?IP ? ? ? ? ? ?NODE ? ? ? ?NOMINATED NODE ? READINESS GATES
nginx-8487c65cfc-cz5hd ? 1/1 ? ? Running ? 0 ? ? ? ? ?3m7s ? 10.244.2.38 ? k8s-node2 ? <none> ? ? ? ? ? <none>
[root@k8s-master ~]# curl 10.244.2.38:8000
?
集群網絡及調度
部署Calico
刪除flannel插件
[root@k8s-master ~]# kubectl delete ?-f kube-flannel.yml
刪除所有節點上flannel配置文件,避免沖突
[root@k8s-master & node1-2 ~]# rm -rf /etc/cni/net.d/xxxxxxx ??? ??? ?# xxx:這里需要自己tab補齊
下載部署文件
# 如果使用的是資源包里面的內容,這里建議上傳而不是下載
[root@k8s-master calico]# curl https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico-typha.yaml -o calico.yaml
更改yml設置
[root@k8s-master calico]# vim calico.yaml
4835 ? ? ? ? ? image: calico/cni:v3.28.1
4835 ? ? ? ? ? image: calico/cni:v3.28.1
4906 ? ? ? ? ? image: calico/node:v3.28.1
4932 ? ? ? ? ? image: calico/node:v3.28.1
5160 ? ? ? ? ? image: calico/kube-controllers:v3.28.1
5249 ? ? ? ? - image: calico/typha:v3.28.14970 ? ? ? ? ? ? - name: CALICO_IPV4POOL_IPIP
4971 ? ? ? ? ? ? ? value: "Never"4999 ? ? ? ? ? ? - name: CALICO_IPV4POOL_CIDR
5000 ? ? ? ? ? ? ? value: "8.3.244.0.0/16"?? ??? ??? ??? ?# 這里使用的是自己的cluster網段(下面有查看網段的命令)
5001 ? ? ? ? ? ? - name: CALICO_AUTODETECTION_METHOD
5002 ? ? ? ? ? ? ? value: "interface=eth0"[root@k8s-master calico]# kubectl apply -f calico.yaml
[root@k8s-master calico]# kubectl -n kube-system get pods
?
?
# 查看集群網段
[root@k8s-master ~]# cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep cidr
測試
[root@k8s-master mnt]# ?kubectl run ?web --image myapp:v1
pod/web created
[root@k8s-master mnt]# kubectl get pods -o wide
web ? ? ? 1/1 ? ? Running ? 0 ? ? ? ? ? ? 10s ? 10.244.169.128 ? k8s-node2 ? <none> ? ? ? ? ? <none>
[root@k8s-master mnt]# curl 10.244.169.128
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
nodename
nodeName 是節點選擇約束的最簡單方法,但一般不推薦;
如果 nodeName 在 PodSpec 中指定了,則它優先于其他的節點選擇方法
使用 nodeName 來選擇節點的一些限制
如果指定的節點不存在。
如果指定的節點沒有資源來容納 pod,則pod 調度失敗。
云環境中的節點名稱并非總是可預測或穩定的
實例
# 建立pod文件
[root@k8s-master mnt]# kubectl run ?testpod ?--image myapp:v1 --dry-run=client -o yaml > pod1.yml
# 查看cluster節點名稱
[root@k8s-master mnt]# kubectl get nodes
NAME ? ? ? ? STATUS ? ROLES ? ? ? ? ? AGE ? VERSION
k8s-master ? Ready ? ?control-plane ? 8d ? ?v1.30.0
k8s-node1 ? ?Ready ? ?<none> ? ? ? ? ?8d ? ?v1.30.0
k8s-node2 ? ?Ready ? ?<none> ? ? ? ? ?8d ? ?v1.30.0# 編寫yml文件并更新
[root@k8s-master mnt]# vim pod1.yml
[root@k8s-master mnt]# kubectl apply -f pod1.yml# 測試
[root@k8s-master mnt]# kubectl get pods -o wide
NAME ? ? ?READY ? STATUS ? ?RESTARTS ? AGE ? IP ? ? ? ? ? ? NODE ? ? ? ?NOMINATED NODE ? READINESS GATES
testpod ? 1/1 ? ? Running ? 0 ? ? ? ? ?12s ? 10.244.36.64 ? k8s-node1 ? <none> ? ? ? ? ? <none># 如果在yml文件中寫了一個不屬于集群的節點,狀態會一直顯示pending
?
Nodeselector(通過標簽控制節點)
-
nodeSelector 是節點選擇約束的最簡單推薦形式
-
給選擇的節點添加標簽
kubectl label nodes <node-name> <label-key>=xxx
kubectl label nodes <node-name> <label-key>-
?
集群認證
ServiceAccount示例
[root@k8s-master ~]# kubectl create sa timinglee
serviceaccount/timinglee created
[root@k8s-master ~]# kubectl describe ?sa timinglee
Name: ? ? ? ? ? ? ? ?timinglee
Namespace: ? ? ? ? ? default
Labels: ? ? ? ? ? ? ?<none>
Annotations: ? ? ? ? <none>
Image pull secrets: ?<none>
Mountable secrets: ? <none>
Tokens: ? ? ? ? ? ? ?<none>
Events: ? ? ? ? ? ? ?<none>
建立secrets
[root@k8s-master ~]# kubectl create secret docker-registry docker-login --docker-username admin --docker-password lee --docker-server reg.timinglee.org --docker-email lee@timinglee.org
secret/docker-login created
[root@k8s-master ~]# kubectl describe secrets docker-login
Name: ? ? ? ? docker-login
Namespace: ? ?default
Labels: ? ? ? <none>
Annotations: ?<none>Type: ?kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: ?119 bytes
將secrets注入到sa中
[root@k8s-master ~]# kubectl edit sa timinglee
apiVersion: v1
imagePullSecrets:
- name: docker-login
kind: ServiceAccount
metadata:
? creationTimestamp: "2024-09-08T15:44:04Z"
? name: timinglee
? namespace: default
? resourceVersion: "262259"
? uid: 7645a831-9ad1-4ae8-a8a1-aca7b267ea2d[root@k8s-master ~]# kubectl describe sa timinglee
Name: ? ? ? ? ? ? ? ?timinglee
Namespace: ? ? ? ? ? default
Labels: ? ? ? ? ? ? ?<none>
Annotations: ? ? ? ? <none>
Image pull secrets: ?docker-login
Mountable secrets: ? <none>
Tokens: ? ? ? ? ? ? ?<none>
Events: ? ? ? ? ? ? ?<none>
建立私有倉庫并且利用pod訪問私有倉
[root@k8s-master auth]# vim example1.yml
[root@k8s-master auth]# kubectl apply -f example1.yml
pod/testpod created
[root@k8s-master auth]# kubectl describe pod testpod
?Warning ?Failed ? ? 5s ? ? ? ? ? ? ? kubelet ? ? ? ? ? ?Failed to pull image "reg.timinglee.org/lee/nginx:latest": Error response from daemon: unauthorized: unauthorized to access repository: lee/nginx, action: pull: unauthorized to access repository: lee/nginx, action: pull
? Warning ?Failed ? ? 5s ? ? ? ? ? ? ? kubelet ? ? ? ? ? ?Error: ErrImagePull
? Normal ? BackOff ? ?3s (x2 over 4s) ?kubelet ? ? ? ? ? ?Back-off pulling image "reg.timinglee.org/lee/nginx:latest"
? Warning ?Failed ? ? 3s (x2 over 4s) ?kubelet ? ? ? ? ? ?Error: ImagePullBackOff
pod綁定sa
[root@k8s-master auth]# vim example1.yml
apiVersion: v1
kind: Pod
metadata:
? name: testpod
spec:
? serviceAccountName: timinglee
? containers:
? - image: reg.timinglee.org/lee/nginx:latest
? ? name: testpod[root@k8s-master auth]# kubectl apply -f example1.yml
pod/testpod created
[root@k8s-master auth]# kubectl get pods
NAME ? ? ?READY ? STATUS ? ?RESTARTS ? AGE
testpod ? 1/1 ? ? Running ? 0 ? ? ? ? ?2s
?