k8s的使用1

Node and Cluster

学习参考:Node

查看节点

bash 复制代码
# 查看节点清单
[root@master30 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE   VERSION
master30.song.cloud   Ready    control-plane   37h   v1.30.2
worker31.song.cloud   Ready    <none>          36h   v1.30.2
worker32.song.cloud   Ready    <none>          36h   v1.30.2

# 查看特定节点详细信息
[root@master30 ~]# kubectl describe node worker31.song.cloud

删除节点

以 worker31 节点为例。

bash 复制代码
# 设置节点为维护模式
[root@master30 ~]# kubectl drain worker31.song.cloud --ignore-daemonsets
node/worker31.song.cloud cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/calico-node-v8jdn, kube-system/kube-proxy-27vl2
evicting pod kube-system/calico-kube-controllers-7cb4fd5784-jx2xl
pod/calico-kube-controllers-7cb4fd5784-jx2xl evicted
node/worker31.song.cloud drained

[root@master30 ~]# kubectl get nodes
NAME                  STATUS                     ROLES           AGE   VERSION
master30.song.cloud   Ready                      control-plane   41h   v1.30.2
worker31.song.cloud   Ready,SchedulingDisabled   <none>          41h   v1.30.2
worker32.song.cloud   Ready                      <none>          41h   v1.30.2

# 删除 worker31 节点
[root@master30 ~]# kubectl delete node worker31.song.cloud
node "worker31.song.cloud" deleted
[root@master30 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE   VERSION
master30.song.cloud   Ready    control-plane   41h   v1.30.2
worker32.song.cloud   Ready    <none>          41h   v1.30.2

# 重置删除的 worker31 节点
[root@worker31 ~]# kubeadm reset -f
[preflight] Running pre-flight checks
W1019 07:37:44.242023    7660 removeetcdmember.go:106] [reset] No kubeadm config, using etcd pod spec to get data directory
[reset] Deleted contents of the etcd data directory: /var/lib/etcd
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Deleting contents of directories: [/etc/kubernetes/manifests /var/lib/kubelet /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]

The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

删除集群

删除集群流程:

  1. 删除所有 node
  2. 删除所有 master

具体步骤:

  1. 删除所有node节点
bash 复制代码
[root@master30 ~]# kubectl drain worker31.song.cloud --ignore-daemonsets --force
[root@master30 ~]# kubectl drain worker32.song.cloud --ignore-daemonsets --force
[root@master30 ~]# kubectl delete node worker31.song.cloud worker32.song.cloud

# 重置节点,注意执行位置
[root@worker31 ~]# kubeadm reset -f
[root@worker32 ~]# kubeadm reset -f
  1. 删除master节点
bash 复制代码
# 删除集群前获取集群配置
[root@master30 ~]# kubectl get cm kubeadm-config -n kube-system -o yaml > kubeadm.yml

# 修改kubeadm.yml内容如下:
[root@master30 ~]# vim kubeadm.yml
# 删除1-3和22-28行,效果如下
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.k8s.io
kind: ClusterConfiguration
kubernetesVersion: v1.30.2
networking:
  dnsDomain: cluster.local
  podSubnet: 10.224.0.0/16
  serviceSubnet: 10.96.0.0/12
scheduler: {}

[root@master30 ~]# kubectl delete node master30.song.cloud
[root@master30 ~]# kubeadm reset -f
[root@master30 ~]# rm -fr .kube/

重建集群

bash 复制代码
# 初始化集群
[root@master30 ~]# kubeadm init --config kubeadm.yml

# 也可以使用之前的命令
[root@master30 ~]# kubeadm init --kubernetes-version=v1.30.2 --pod-network-cidr=10.224.0.0/16

# 配置凭据
[root@master30 ~]# mkdir -p $HOME/.kube
[root@master30 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master30 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 配置网络
[root@master30 ~]# kubectl apply -f calico.yaml

# 加入集群
[root@worker31 ~]# kubeadm join 10.1.8.30:6443 --token ky95b9.sjg0fn21pdi1m0xz    --discovery-token-ca-cert-hash sha256xxxxxxx
[root@worker32 ~]# kubeadm join 10.1.8.30:6443 --token ky95b9.sjg0fn21pdi1m0xz    --discovery-token-ca-cert-hash sha256xxxxxxx

Namespace and Contexts

学习参考:Namespace

Namespace 介绍

**问题:**多个用户使用同一个Kubernetes Cluster, 如何将他们创建的资源隔离开呢?

答案:Namespace ,简写ns,也称之为 project,代表资源集合,用于分组集群资源。Kubernetes 使用 Namespace 可以将一个物理的 Cluster 逻辑上划分成多个资源集合, 每个集合就是一个Namespace。 不同Namespace 里的资源是完全隔离的。

Kubernetes 默认创建以下Namespace:

  • default: 创建资源时如果不指定Namespace, 将被放到这个Namespace中。
  • kube-system: Kubernetes 自己创建的系统资源将放到这个Namespace中。
  • kube-public:该命名空间中所有对象可以被所有用户(包括未验证身份的用户)读取。
  • kube-node-lease:该命名空间含有与每个节点关联的Lease对象。节点租用允许kubelet发送heartbeat(心跳),以便控制平面能检测节点故障。

思考:所有对象都属于 Namespace 吗?

**答:**大多数Kubernetes资源(例如 pod、services、pvc等)都属于某个Namespace,但 Namespace 资源本身并不在 Namespace 中,更低级别资源(如Node和persistentVolumes)也不在任何Namespace中。

Namespace 管理

bash 复制代码
# 查看Namespace清单
[root@master30 ~]# kubectl get ns
NAME              STATUS   AGE
default           Active   7d4h
kube-node-lease   Active   7d4h
kube-public       Active   7d4h
kube-system       Active   7d4h

# 获取Namespace资源yaml格式定义文件
[root@master30 ~]# kubectl get ns default -o yaml

# 创建Namespace
[root@master30 ~]# kubectl create ns song
# 注意:命名空间名称满足正则表达式[a-z0-9]([-a-z0-9]*[a-z0-9])?,最大长度为63位

# 直接编辑Namespace
[root@master30 ~]# kubectl edit ns song

# 查看Namespace详细信息
[root@master30 ~]# kubectl describe ns song
Name:         song
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota.

No LimitRange resource.

# 删除Namespace
[root@master30 ~]# kubectl delete ns song
namespace "song" deleted
# 注意:
# 删除一个namespace会自动删除该namespace中所有资源。
# default和kube-system命名空间不可删除。

Namespace 还可以通过 yaml 文件创建。

yaml 复制代码
# ns-song.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: song
bash 复制代码
[root@master30 ~]# kubectl apply -f ns-song.yaml 
namespace/song created

操作特定ns中对象,需要使用选项-n指定ns,例如:

bash 复制代码
[root@master30 ~]# kubectl run web --image=nginx -n song
pod/web created

[root@master30 ~]# kubectl get pod -n song -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP               NODE                   NOMINATED NODE   READINESS GATES
web    1/1     Running   0          39s   10.224.113.129   worker32.song.cloud   <none>           <none>

[root@master30 ~]# curl -s 10.224.113.129  | grep nginx
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
<a href="https://nginx.org/">nginx.org</a>.<br/>
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/>
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p>
<p><em>Thank you for using nginx.</em></p>

Namespace 切换

kubectl

查看当前所在ns

bash 复制代码
[root@master30 ~]# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO          NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

此时NAMESPACE列对应的属性为空,不属于任何NAMESPACE

设置默认ns

bash 复制代码
[root@master30 ~]# kubectl config set-context --current --namespace=song
Context "kubernetes-admin@kubernetes" modified.
[root@master30 ~]# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO        NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   song

此时,NAMESPACE 列对应的属性为 song。

kubens

kubens 安装

bash 复制代码
[root@master30 ~]# wget https://codeload.github.com/ahmetb/kubectx/zip/refs/heads/master -O kubectx.zip
[root@master30 ~]# unzip kubectx.zip
[root@master30 ~]# ls kubectx-master/
CONTRIBUTING.md  README.md  completion  go.sum  internal  kubens
LICENSE          cmd        go.mod      img     kubectx   test
[root@master30 ~]# cp kubectx-master/kubens /usr/local/bin/
[root@master30 ~]# chmod +x /usr/local/bin/kubens

# 配置补全
[root@master30 ~]# cp kubectx-master/completion/kubens.bash /etc/bash_completion.d/
[root@master30 ~]# source /etc/bash_completion.d/kubens.bash

kubens 命令使用

bash 复制代码
[root@master30 ~]# kubens -h
USAGE:
  kubens                    : list the namespaces in the current context
  kubens <NAME>             : change the active namespace of current context
  kubens -                  : switch to the previous namespace in this context
  kubens -c, --current      : show the current namespace
  kubens -h,--help          : show this message

[root@master30 ~]# kubens 
default
kube-node-lease
kube-public
kube-system
song

[root@master30 ~]# kubens kube-system
[root@master30 ~]# kubectl config get-contexts

CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   kube-syste

[root@master30 ~]# kubectl get pods
NAME                                          READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7cb4fd5784-dqv6n      1/1     Running   0          19m
calico-node-5k2bp                             1/1     Running   0          18m
calico-node-6vpt6                             1/1     Running   0          19m
calico-node-7x82d                             1/1     Running   0          19m
coredns-66f779496c-h89xx                      1/1     Running   0          19m
coredns-66f779496c-zqqxd                      1/1     Running   0          19m
etcd-master30.song.cloud                      1/1     Running   2          19m
kube-apiserver-master30.song.cloud            1/1     Running   2          19m
kube-controller-manager-master30.song.cloud   1/1     Running   2          19m
kube-proxy-7l9pr                              1/1     Running   0          19m
kube-proxy-9djwp                              1/1     Running   0          19m
kube-proxy-n2bk9                              1/1     Running   0          18m
kube-scheduler-master30.song.cloud            1/1     Running   2          19m

自定义脚本

bash 复制代码
#!/bin/bash
function usage(){
  echo "$0 [namespace]
1. 没有namespace参数时,显示namespace清单
2. namespace必须是集群中存在的namespace"
}

# 获取当前namespace
namespace=$(kubectl config get-contexts | awk '/\*/{print $5}')
if [ -z "$namespace" ];then
  namespace=default
fi

# 显示 namespace清单
if [ $# -eq 0 ];then
  kubectl get ns | awk '{print "  "$1}' | sed "s/^  $namespace/\* $namespace/"
  exit 1
fi

# 切换 namespace
if [ $# -eq 1 ];then
  if kubectl get ns | awk '$1 !~ "NAME" {print $1}' | grep -qx "$1" &>/dev/null;then
    kubectl config set-context --current --namespace $1 > /dev/null
    echo "当前namespace设置为:$1"
  else
    usage  
  fi
fi

Cluster 切换

~/.kube/config 详解

单集群配置

获取凭据文件内容(不显示敏感信息):

bash 复制代码
[root@master30 ~]# kubectl config view
yaml 复制代码
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.1.8.30:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: kube-system
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

配置文件示例:

yaml 复制代码
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EUXdNakExTURZd05Wb1hEVE15TURNek1EQTFNRFl3TlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHg5ClZnNGUyR3dUTkVUaUowTjBqV09hZ2NvQVRnclFzVXVjWU1Jb281YWFZZGtTZGY2amdJanhTeEtNTmZyL3MrQWQKems5S25CL2UwS0ZxSEJwOEhsQy9VZ0JTK1V2THl6b2VuWVNFM29MWmJzdDhwY1JXL0ZWQVdQckRkS1VhcTdJcApyVXpvQlRTSHRHSEluNitLR1htZ3BwWkdLK3pRT2pjTWYyT2IxOGZ0NDZDbXNFT24rMmhKZk13eHBUd3k0dEgvCktteWhnVStYUys1c0Z5L0N2R1gwbUEzbWpzeHZ4VnFmamQ0T2F0RVVhamN5aERVc3FxRVVBUmNWZGdpbkhUc2IKdWVhc3NieUFZSGRJWGFiMjQvVzg0ZXpDYk8vMGhvcHhZZFhGVDYxQVc3R2RNL0IvNlYyU0hDWUFCd2FKU1dmNApZWHFpajJoMndUNDdYZHZscHNzQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLWlJpc2FLS1c4YjFFcUlHeHhTcTkrdUdEWFNNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRjhHSjI1c1RqVEd3RDRoSDVmegp5bXU2WGhSd212ejBzemNKUTVKVVlsSndpUlJ0NUVBZ2lNUHZ0MndIeGt1UExGWDAwRFZ2MWorQkEzaEt5Wk5GClVaQUdrRmVwK0JyOWZYUWxVSE15OHZTZjFZSVhBRk43MFdBT0dFdVZjWEJDeDFNbWlBTndObUQyck1LdmFJK1cKci80Y1hMdXdVZlNUaUZaeFpaVGdaRkFtSFJ0QnVvSmpoaStmQjRPT2xTRFNEMU9PaFZjVVc3bWo3YkhJUjN1cgpzRnFYakp5eEc0T0JadlM5MTBXMUNtYTJWUTFCYnprY1h0YzJZOUdDSS9Cd3h2a0labWFSYy9ETFY1M0YxSmxXCnluNmovZEpvdmd6SGZqaVhheUxoekpaUDhMaG9ULzFacFQ2K214Uml0SHVMM2RVRW9oL2ttSzZqclBjZlFUWlMKTnRrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.1.8.30:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJYm9pOWR1alB4dEF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TWpBME1ESXdOVEEyTURWYUZ3MHlNekEwTURJd05UQTJNRGRhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXhSbWh6MkpjWG83RmNIb1QKQ0d6dHkyRGplM1FvYVl1djVMMmV2V3NpMk14SmZRLzVnRWg4cDdXZEdTQ0NDL0t5a2Fvbk9ZWFh3MkxEVi9yVQpkbEtNbUtTN2s1eG5WWWV1M0EyZGlCMTU1MVVFK0lTelVPTE54c3J0MjdVajRuMDliUU5kSzhjeEZvclhxVUV0ClppVTdHY0dOZ3hRUVA4MkhGSDdTb09RTXRtTmo0bXdMWHVZbEFWODZ5TXl5RThQYjF5Y0FoQjhVY1BFUmRUeWQKeEtUY3FVbG0xYnQ4cU1CRzlYWUZFNk1IUUpldXk0Rnk3NjlYL2ZJNk9SZCtuUGdVWHVVd0FUYVdYR2JIeWhoUApDS0dKWXdzY09PRUFmWnRWV3RYUkxiM1pEWWpiVmFqTzllT0ZHYnorcjRxVDR2NEpkL1dZZ1RLcmUvTDBzVlhRCkROZWZDd0lEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JTbVVZckdpaWx2RzlSS2lCc2NVcXZmcmhnMQowakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBckt4cjhFbEtYN2FYWUMvdzZhUFg4M3JvRHl0Q0NudTBTMHpWCm5WTVFnMUsvUmhRSGV5TnY2SGtycTJXSFhoUjh1L2M3Ukw3WGwyeDlzcWhPWmR3cGRrUlBXK0RENEs4TFMwYjAKUnhwdGxraW44UFE5QkZEOExuNDlmdmNhRG9LT0lhV2djZFFVMFRKQVZoZ1RNQ3FZZ0ZNTUhQa3I2d2Q2WVFtMgp3KzhsVlNCNytmeERKVlhkeUZWMFdOdk5Jb1JrM0FCcGEyOVVVZlZoY1FnZGI2M1RFamgwUlI0d014bjhhY2E1CnNiaE1wVmZiT2ZUU0pRTUJGRkRkMG5DWnJSN3NxQWluOUE2M3RydWZLTzJMTEF0YUVJeDRMUzJWZ09veG5odWEKQlh6UGp4SHF5TTR1WFRqQVlOMk44K2wxWXRBeSs0VTg2ZzVEMEZZeUpSTE5NMU5VL2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeFJtaHoySmNYbzdGY0hvVENHenR5MkRqZTNRb2FZdXY1TDJldldzaTJNeEpmUS81CmdFaDhwN1dkR1NDQ0MvS3lrYW9uT1lYWHcyTERWL3JVZGxLTW1LUzdrNXhuVllldTNBMmRpQjE1NTFVRStJU3oKVU9MTnhzcnQyN1VqNG4wOWJRTmRLOGN4Rm9yWHFVRXRaaVU3R2NHTmd4UVFQODJIRkg3U29PUU10bU5qNG13TApYdVlsQVY4NnlNeXlFOFBiMXljQWhCOFVjUEVSZFR5ZHhLVGNxVWxtMWJ0OHFNQkc5WFlGRTZNSFFKZXV5NEZ5Cjc2OVgvZkk2T1JkK25QZ1VYdVV3QVRhV1hHYkh5aGhQQ0tHSll3c2NPT0VBZlp0Vld0WFJMYjNaRFlqYlZhak8KOWVPRkdieityNHFUNHY0SmQvV1lnVEtyZS9MMHNWWFFETmVmQ3dJREFRQUJBb0lCQUNkS0hMOUNWRGRsTG1abApielhXd1BBeHVDYjcyTEp4YmZhaTllbThXWTN0NnhoSy91bGJpYjNFcmpROERyQmpDTVdRclpFQjVTakZuenNDCmZTZTQvTjNRdUxPTUVlMHl4dUNHdGtoVDErRU5TWmhnbTM0Y04valFxdW1KQ2tZendQTGlJTWlCUkgvQjNZdVgKdW4wS0h1WGJkMklSdGN1Q0pOTXBGTU9Oc2hzSkMyRTI1cmhXazlZZFdKTVVQV2JjMGZUd0RDdHhVSXpRNWhycApOa0tGenpBekdiVFA2dXA2dWJrYzQ4Zm9BNDVTRUJLNkhhcFZBNEQ1NzNQNFNmZWRodmhMVG9lbmQzM3NmeTJYCjlkS1dFOUg4VUQ3VGFRc3N6MG8xSU1xK0xVVU5UNUVqRkVCOXVtemIxTHB4YW1wUFJqVVpXU2ZEcXJDbGlvMkUKWHFaWkd3RUNnWUVBMm5Tbmd2R0p2NUZhdFVQeGppbWMyNHhOWjZSTWhRRFc3OG9TRUYrUUVoV2RscGlwTk94QQpVNTJNY1NrSmNMR1Jkd3VIaWdjQXVWVW90N09sak9MU1Zzak4yN0xRQTFraTNXbjYxeWVKUSs5MVpZMW9GaUJQCmpBZWJoS1BJanFPT2p3YUsrMEJ5cGFJb2dTb215dzErNklrSE5kNmJkc2FQbG1aMU9wc0hjRHNDZ1lFQTV2bG0KOGNvUUlEWWx5Q0x3YzMzSWRHd0xsWU9KUmFNdCs5QXRNY1VaZGZZN2gvaUlWTE4wSEZkUUFkOWxLUUxyNlpZVApuS0lWcUdzU1BiM2kyMCsyZHNVN3VPUjNOVkZCeHcvZUVVM1FnTjFtVTRnZzBLNnpORUpkKzZaYVo2cUQyVVhRCnY3cTdiOHhzekJoUkNMakdjb1huL2ZnWFBIWmRDUE9VVUVIWTczRUNnWUVBek1RSHVDK2JoSnRFd1IvY3JmckgKY3V1Q0txSFFyK0xubFlCOWlpZHBMZXBnK3FaQ0JMOW1WSG9iQ0g4RXdFTlJMSnI4QXg4cFNJOVFTVkQwM3FoRgpyTjh3UnJ6SFNqd2srQkc4OUN1MCtKN2VGY0NFVGlrZkp3eUNjOFBwMi9ublNKMURiTnN1RzU5eUJCQjBxR1FRCkR2dFNiT1lxSngxYnZnaHYzZTB1L2IwQ2dZRUF4NHc1TURQT2NzWFZKbTlwSlo1S0RLczc1dFJaU0Z5T1lidWQKRUI2a3ZKRWJKWUhHNXNhVFRkanhPbXp5VE5oRlVPMWp6RE1NV3hFR0ZXbDBFTjF4V25OVUFZMEFvSU92UEhlcwo5MjR1OE9aV2ZWeGlYV2hSVXBqejhYSHJNUnpVQkdhWXpzeFpHMkdWclU1azFCQXZBc3BGZjlsUzJkMjR5djhGCjU4QzcxMEVDZ1lBV0p4NmpuV05vbGc1QzhvSGpDT0Jkb0RGdHhGeEpiT2M5QUJ2aHpZbGlTSHp5aTY3RjVQZ28KREdaWXJjWWZxYVY5MVl5R24xaWQybG5GcVZoZ1VGYnpGS2t4U0FaS0FJVDRwbGNucVRWQm9oc1UwMkxqSUdEZwpESU5SQW8xb0dqRTdOM3FWUVFzS0huSDBnUXNwWVZpN3NFRzRDdWtZSDQ2MUNCM0dET0N0b3c9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

说明:

  • certificate-authority-data 指定CA证书,通过base64编码。
bash 复制代码
[root@master30 ~]# echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJYm9pOWR1alB4dEF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TWpBME1ESXdOVEEyTURWYUZ3MHlNekEwTURJd05UQTJNRGRhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXhSbWh6MkpjWG83RmNIb1QKQ0d6dHkyRGplM1FvYVl1djVMMmV2V3NpMk14SmZRLzVnRWg4cDdXZEdTQ0NDL0t5a2Fvbk9ZWFh3MkxEVi9yVQpkbEtNbUtTN2s1eG5WWWV1M0EyZGlCMTU1MVVFK0lTelVPTE54c3J0MjdVajRuMDliUU5kSzhjeEZvclhxVUV0ClppVTdHY0dOZ3hRUVA4MkhGSDdTb09RTXRtTmo0bXdMWHVZbEFWODZ5TXl5RThQYjF5Y0FoQjhVY1BFUmRUeWQKeEtUY3FVbG0xYnQ4cU1CRzlYWUZFNk1IUUpldXk0Rnk3NjlYL2ZJNk9SZCtuUGdVWHVVd0FUYVdYR2JIeWhoUApDS0dKWXdzY09PRUFmWnRWV3RYUkxiM1pEWWpiVmFqTzllT0ZHYnorcjRxVDR2NEpkL1dZZ1RLcmUvTDBzVlhRCkROZWZDd0lEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JTbVVZckdpaWx2RzlSS2lCc2NVcXZmcmhnMQowakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBckt4cjhFbEtYN2FYWUMvdzZhUFg4M3JvRHl0Q0NudTBTMHpWCm5WTVFnMUsvUmhRSGV5TnY2SGtycTJXSFhoUjh1L2M3Ukw3WGwyeDlzcWhPWmR3cGRrUlBXK0RENEs4TFMwYjAKUnhwdGxraW44UFE5QkZEOExuNDlmdmNhRG9LT0lhV2djZFFVMFRKQVZoZ1RNQ3FZZ0ZNTUhQa3I2d2Q2WVFtMgp3KzhsVlNCNytmeERKVlhkeUZWMFdOdk5Jb1JrM0FCcGEyOVVVZlZoY1FnZGI2M1RFamgwUlI0d014bjhhY2E1CnNiaE1wVmZiT2ZUU0pRTUJGRkRkMG5DWnJSN3NxQWluOUE2M3RydWZLTzJMTEF0YUVJeDRMUzJWZ09veG5odWEKQlh6UGp4SHF5TTR1WFRqQVlOMk44K2wxWXRBeSs0VTg2ZzVEMEZZeUpSTE5NMU5VL2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== | base64 -d
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIIboi9dujPxtAwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yMjA0MDIwNTA2MDVaFw0yMzA0MDIwNTA2MDdaMDQx
FzAVBgNVBAoTDnN5c3RlbTptYXN0ZXJzMRkwFwYDVQQDExBrdWJlcm5ldGVzLWFk
bWluMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxRmhz2JcXo7FcHoT
CGzty2Dje3QoaYuv5L2evWsi2MxJfQ/5gEh8p7WdGSCCC/KykaonOYXXw2LDV/rU
dlKMmKS7k5xnVYeu3A2diB1551UE+ISzUOLNxsrt27Uj4n09bQNdK8cxForXqUEt
ZiU7GcGNgxQQP82HFH7SoOQMtmNj4mwLXuYlAV86yMyyE8Pb1ycAhB8UcPERdTyd
xKTcqUlm1bt8qMBG9XYFE6MHQJeuy4Fy769X/fI6ORd+nPgUXuUwATaWXGbHyhhP
CKGJYwscOOEAfZtVWtXRLb3ZDYjbVajO9eOFGbz+r4qT4v4Jd/WYgTKre/L0sVXQ
DNefCwIDAQABo1YwVDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH
AwIwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSmUYrGiilvG9RKiBscUqvfrhg1
0jANBgkqhkiG9w0BAQsFAAOCAQEArKxr8ElKX7aXYC/w6aPX83roDytCCnu0S0zV
nVMQg1K/RhQHeyNv6Hkrq2WHXhR8u/c7RL7Xl2x9sqhOZdwpdkRPW+DD4K8LS0b0
Rxptlkin8PQ9BFD8Ln49fvcaDoKOIaWgcdQU0TJAVhgTMCqYgFMMHPkr6wd6YQm2
w+8lVSB7+fxDJVXdyFV0WNvNIoRk3ABpa29UUfVhcQgdb63TEjh0RR4wMxn8aca5
sbhMpVfbOfTSJQMBFFDd0nCZrR7sqAin9A63trufKO2LLAtaEIx4LS2VgOoxnhua
BXzPjxHqyM4uXTjAYN2N8+l1YtAy+4U86g5D0FYyJRLNM1NU/g==
-----END CERTIFICATE-----
  • client-certificate-data 指定用户证书,同样是 base64 编码。
  • client-key-data 指定用户私钥,同样是 base64 编码。
bash 复制代码
# 或者使用以下命令获取不显示具体证书和key内容
[root@master30 ~]# kubectl config view
yaml 复制代码
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.1.8.30:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
多集群配置

示例:/root/multi-cluster-config

yaml 复制代码
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.1.8.30:6443
  name: cluster1
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.1.8.150:6443
  name: cluster2
contexts:
- context:
    cluster: cluster1
    namespace: default
    user: cluster1-admin
  name: cluster1-context
- context:
    cluster: cluster2
    namespace: default
    user: cluster2-admin
  name: cluster2-context
current-context: cluster1-context
kind: Config
preferences: {}
users:
- name: cluster1-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
- name: cluster2-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

配置文件定义了以下资源:

  • clusters:集群信息,包括集群名、authority、地址和端口。
  • users:用户信息,包括用户名、certificate和key。
  • contexts:上下文信息,包括上下文名称、集群名、用户名和namespace。

多集群切换

kubernetes 自带工具

环境准备:

bash 复制代码
[root@master30 ~]# cp .kube/config .kube/config.ori
[root@master30 ~]# cp multi-cluster-config .kube/config

查看集群清单

bash 复制代码
[root@master30 ~]# kubectl config get-clusters
NAME
cluster1
cluster2

查看上下文清单

bash 复制代码
[root@master30 ~]# kubectl config get-contexts
CURRENT   NAME               CLUSTER    AUTHINFO         NAMESPACE
*         cluster1-context   cluster1   cluster1-admin   default
          cluster2-context   cluster2   cluster2-admin   default

* 代表当前使用的上下文

切换上下文

bash 复制代码
[root@master30 ~]# kubectl config use-context cluster2-context
[root@master30 ~]# kubectl config get-contexts
CURRENT   NAME               CLUSTER    AUTHINFO         NAMESPACE
          cluster1-context   cluster1   cluster1-admin   default
*         cluster2-context   cluster2   cluster2-admin   default
kubectx-第三方工具

kubectx 安装

bash 复制代码
[root@master30 ~]# wget https://codeload.github.com/ahmetb/kubectx/zip/refs/heads/master -O kubectx.zip
[root@master30 ~]# unzip kubectx.zip
[root@master30 ~]# ls kubectx-master/
CONTRIBUTING.md  README.md  completion  go.sum  internal  kubens
LICENSE          cmd        go.mod      img     kubectx   test
[root@master30 ~]# cp kubectx-master/kubectx /usr/local/bin/
[root@master30 ~]# chmod +x /usr/local/bin/kubectx

# 配置补全
[root@master30 ~]# cp kubectx-master/completion/kubectx.bash /etc/bash_completion.d/
[root@master30 ~]# source /etc/bash_completion.d/kubectx.bash

kubectx 帮助

bash 复制代码
[root@master30 ~]# kubectx -h
USAGE:
  kubectx                       : list the contexts
  kubectx <NAME>                : switch to context <NAME>
  kubectx -                     : switch to the previous context
  kubectx -c, --current         : show the current context name
  kubectx <NEW_NAME>=<NAME>     : rename context <NAME> to <NEW_NAME>
  kubectx <NEW_NAME>=.          : rename current-context to <NEW_NAME>
  kubectx -d <NAME> [<NAME...>] : delete context <NAME> ('.' for current-context)
                                  (this command won't delete the user/cluster entry
                                  that is used by the context)
  kubectx -u, --unset           : unset the current context

  kubectx -h,--help             : show this message

kubectx 命令使用

bash 复制代码
[root@master30 ~]# kubectx
cluster1-context
cluster2-context
[root@master30 ~]# kubectx -c
cluster2-context

[root@master30 ~]# kubectx cluster1-context
Switched to context "cluster1-context".
[root@master30 ~]# kubectx -c


cluster1-context

[root@master30 ~]# kubectx -u
Unsetting current context.
Property "current-context" unset.
[root@master30 ~]# kubectx -c
error: current-context is not set

Kubernetes Pod

学习参考:Pod

环境准备

bash 复制代码
[root@master30 ~]# kubectl create ns pods
[root@master30 ~]# kubectl config set-context --current --namespace pods

Pod 介绍

pod 代表一个deployment单元:a single instance of an application in Kubernetes。

k8s通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定镜像,用来运行具体的服务。Pod代表集群上正在运行的一个进程,一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

  • 运行单个容器的 Pod:将Pod看作是单个容器的包装器,kubernetes管理pods而不是直接管理容器。

  • 运行多个容器的 Pod :POD可以封装一个由多个共存容器组成的应用程序。pod中的容器会自动在集群中的同一物理机或虚拟机上运行。POD中多个容器共享资源和依赖项,彼此通信,以及协调何时以及如何终止它们。POD将这些容器、网络资源和存储资源作为一个单一的可管理实体包装在一起。pod中多个容器共享网络和存储资源。每个pod分配唯一的ip地址,pod中容器共享netns,包括ip地址和port端口。多个容器之间使用localhost通信。当pod中容器与其他pod通信,需要使用共享的网络资源。pod可以使用多个volume,pod中所有容器都可以访问这些卷。

白话解释: 可以把pod看成是一个"豌豆荚",里面有很多"豆子"(容器)。一个豌豆荚里的豆子,它们吸收着共同的营养成分、肥料、水分等,Pod和容器的关系也是一样,Pod里面的容器共享pod的网络、存储等。

例如:web容器提供文件共享,另外一个容器负责更新文件内容。

pod 基本管理

创建 pod

bash 复制代码
# 空运行,只生成yaml文件
[root@master30 ~]# kubectl run web --image=hub.laoma.cloud/library/nginx --dry-run=client -o yaml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: web
  name: web
spec:
  containers:
  - image: hub.laoma.cloud/library/nginx
    name: web
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
bash 复制代码
# 直接创建pod
[root@master30 ~]# kubectl run web --image=hub.laoma.cloud/library/nginx
pod/web created

[root@master30 ~]# kubectl get pod
NAME   READY   STATUS              RESTARTS   AGE
web    0/1     ContainerCreating   0          36s

[root@master30 ~]# kubectl get pod
NAME   READY   STATUS    RESTARTS   AGE
web    1/1     Running   0          51s

[root@master30 ~]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE               NOMINATED NODE   READINESS GATES
web    1/1     Running   0          67s   10.224.51.131   worker31.laoma.cloud   <none>           <none>

[root@master30 ~]# ssh root@worker31 nerdctl ps --namespace k8s.io |grep web
[root@master30 ~]# ssh root@worker31 nerdctl images --namespace k8s.io |grep nginx

查看 pod

bash 复制代码
# 以yaml格式查看pod
[root@master30 ~]# kubectl get pod web -o yaml

# 查看pod
[root@master30 ~]# kubectl describe pod web

# 查看pod标准输出,可以是哟个选项-f动态查看pod输出
[root@master30 ~]# kubectl logs -f web 

编辑 pod

bash 复制代码
[root@master30 ~]# kubectl edit pod web

提示:并不是所有属性都可以编辑,例如pod名称。如果非要编辑特定属性,可以先删除pod,然后修改pod对的yaml文件,重新创建。

pod 中执行命令

bash 复制代码
[root@master30 ~]# kubectl exec web -- hostname
web
[root@master30 ~]# kubectl exec web -- pwd
/
[root@master30 ~]# kubectl exec -it web -- bash -c 'echo Hello World > htdocs/index.html'
[root@master30 ~]# kubectl exec web -- id
uid=0(root) gid=0(root) groups=0(root)

cp 文件给 pod

bash 复制代码
[root@master30 ~]# kubectl cp /etc/hosts web:/new-hosts
[root@master30 ~]# kubectl exec web -- ls /new-hosts
/new-hosts

删除 pod

bash 复制代码
[root@master30 ~]# kubectl delete pod web
pod "web" deleted

删除时间

bash 复制代码
[root@master30 ~]# kubectl get pod web -o yaml|grep ' terminationGracePeriodSeconds'
terminationGracePeriodSeconds: 30

yaml 文件创建 pod

yaml 复制代码
# web.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: web
  name: web
spec:
  containers:
  - image: hub.laoma.cloud/library/nginx
    name: web
bash 复制代码
[root@master30 ~]# kubectl create -f web.yaml
# 或者
[root@master30 ~]# kubectl apply -f web.yaml

综合实验:构建 wordpreess

  1. 创建 pod-mysql 数据库
  2. 创建 pod-wordpress 博客

参考步骤:

bash 复制代码
# 创建 pod-mysql 数据库
[root@master30 ~]# kubectl run wordpress-db --image=mysql --image-pull-policy IfNotPresent --env MYSQL_ROOT_PASSWORD=123

# 创建 pod-wordpress 博客
[root@master30 ~]# kubectl run wordpress-app --image=wordpress --image-pull-policy IfNotPresent

# 实现集群外访问集群内pod
[root@master30 ~]# kubectl port-forward pod/wordpress-app --address 10.1.8.30 8080:80
# 该命令窗口不要关闭

# 查看 IP
[root@master30 ~]# kubectl get pods -o wide | awk '{print $1" "$6}'
NAME IP
wordpress-app 10.224.113.135
wordpress-db 10.224.19.5

# 创建数据库
[root@master30 ~]# mysql -uroot -p123 -h 10.224.19.5
mysql> create database wordpress;
mysql> create user wordpress identified by '123';
mysql> grant all privileges on wordpress.* to wordpress;
mysql> flush privileges;
mysql> exit

访问web页面 http://10.1.8.30:8080,配置站点。

多容器 pod

示例文件:blog.yaml

bash 复制代码
[root@master30 ~]# vim pod-blog.yaml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: bbs
  labels:
    run: bbs
spec:
  containers:
  - image: hub.laoma.cloud/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "123"
    - name: MYSQL_USER
      value: tom
    - name: MYSQL_PASSWORD
      value: "123"
    - name: MYSQL_DATABASE
      value: bbs
    ports:
    - containerPort: 3306
      name: mysql
      protocol: TCP
  - image: hub.laoma.cloud/library/wordpress:latest
    imagePullPolicy: IfNotPresent
    name: wordpress
    env:
    - name: WORDPRESS_DB_USER
      value: tom
    - name: WORDPRESS_DB_PASSWORD
      value: "123"
    - name: WORDPRESS_DB_NAME
      value: bbs
    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1
    ports:
    - containerPort: 80
      name: wordpress
      protocol: TCP
      hostPort: 80
bash 复制代码
[root@master30 ~]# kubectl apply -f pod-blog.yaml

# 查看 pod 运行节点
[root@master30 ~]# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE               NOMINATED NODE   READINESS GATES
bbs    2/2     Running   0          10m   10.224.225.68   worker32.laoma.cloud   <none>           <none>

# 多容器pod中执行命令,通过-c指定容器
[root@master30 ~]# kubectl exec bbs -c wordpress -- hostname
bbs
[root@master30 ~]# kubectl cp /etc/hosts bbs:/new-hosts -c wordpress
[root@master30 ~]# kubectl exec bbs -c wordpress -- ls /new-hosts
/new-hosts

数据库访问测试

bash 复制代码
[root@master30 ~]# kubectl exec -it bbs -c mysql -- mysql -utom -p123
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

使用所在宿主机的80端口访问:http://10.1.8.32/

pod 关键属性

bash 复制代码
[root@master30 ~]# kubectl explain pod | grep '^  [a-zA-Z]'
  apiVersion	<string>
  kind	<string>
  metadata	<ObjectMeta>
  spec	<PodSpec>
  status	<PodStatus>

pod.metadata

bash 复制代码
[root@master30 ~]# kubectl explain pod.metadata | grep '^  [a-zA-Z]'
   annotations	<map[string]string>
   clusterName	<string>
   creationTimestamp	<string>
   deletionGracePeriodSeconds	<integer>
   deletionTimestamp	<string>
   finalizers	<[]string>
   generateName	<string>
   generation	<integer>
   labels	<map[string]string>
   managedFields	<[]Object>
   name	<string>
   namespace	<string>
   ownerReferences	<[]Object>
   resourceVersion	<string>
   selfLink	<string>
   uid	<string>

需要关注的属性:labels,name,namespace,deletionGracePeriodSeconds。

pod.spec

bash 复制代码
[root@master30 ~]# kubectl explain pod.spec | grep '^  [a-zA-Z]'
   activeDeadlineSeconds	<integer>
   affinity	<Object>
   automountServiceAccountToken	<boolean>
   containers	<[]Object> -required-
   dnsConfig	<Object>
   dnsPolicy	<string>
   enableServiceLinks	<boolean>
   ephemeralContainers	<[]Object>
   hostAliases	<[]Object>
   hostIPC	<boolean>
   hostNetwork	<boolean>
   hostPID	<boolean>
   hostname	<string>
   imagePullSecrets	<[]Object>
   initContainers	<[]Object>
   nodeName	<string>
   nodeSelector	<map[string]string>
   overhead	<map[string]string>
   preemptionPolicy	<string>
   priority	<integer>
   priorityClassName	<string>
   readinessGates	<[]Object>
   restartPolicy	<string>
   runtimeClassName	<string>
   schedulerName	<string>
   securityContext	<Object>
   serviceAccount	<string>
   serviceAccountName	<string>
   setHostnameAsFQDN	<boolean>
   shareProcessNamespace	<boolean>
   subdomain	<string>
   terminationGracePeriodSeconds	<integer>
   tolerations	<[]Object>
   topologySpreadConstraints	<[]Object>
   volumes	<[]Object>

重点关注:containers、nodeName、volumes等。

pod.spec.containers
bash 复制代码
[root@master30 ~]# kubectl explain pod.spec.containers | grep '^   [a-zA-Z]'
   args	<[]string>
   command	<[]string>
   env	<[]Object>
   envFrom	<[]Object>
   image	<string>
   imagePullPolicy	<string>
   lifecycle	<Object>
   livenessProbe	<Object>
   name	<string> -required-
   ports	<[]Object>
   readinessProbe	<Object>
   resources	<Object>
   securityContext	<Object>
   startupProbe	<Object>
   stdin	<boolean>
   stdinOnce	<boolean>
   terminationMessagePath	<string>
   terminationMessagePolicy	<string>
   tty	<boolean>
   volumeDevices	<[]Object>
   volumeMounts	<[]Object>
   workingDir	<string>

重点关注:command、env、image、imagePullPolicy、volumeMounts等。

pod.spec.containers.ImagePullPolicy
  • Always,总是从仓库下载镜像。
  • Never,只使用本地镜像,不下载。
  • IfNotPresent,优先使用本地镜像,如果没有才从仓库下载镜像。
pod lifecycle 和 status
pod lifecycle
  • pod的生命周期取决于pod中所有容器的生命周期。
  • 容器的生命周期取决于容器中进程的生命周期。
Pod status

常见 pod 状态如下:

  • ContainerCreating 正在创建
  • Running 正在运行
  • Completed 运行完成
  • Error/RunContainerError 运行错误
  • CrashLoopBackOff 重新创建
  • ErrImagePull 获取镜像错误
  • ImagePullBackOff 重新获取镜像
  • Terminating,正在终止(删除)

实验1:pod中包含1个容器,验证pod状态

监控命令: watch -n 1 kubectl get pod

示例1:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']

command命令可以改写如下:

yaml 复制代码
command:
- sh
- -c
- echo OK! && sleep 10

或者

yaml 复制代码
args:
- sh
- -c
- echo OK! && sleep 10

观察pod状态为:ContainerCreating-->Running-->Completed

示例2:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

观察pod状态为:ContainerCreating-->Error

实验2:pod中包含2个容器,验证pod状态

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']

观察pod状态为:ContainerCreating-->Running-->NotReady(其中一个先完成)-->Completed(两个都完成)

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxx Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 20']

观察pod状态为:ContainerCreating-->Error

pod.spec.restartPolicy

示例:

yaml 复制代码
  restartPolicy: Never
  containers:
  - name: myapp-container
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 5'] 

restartPolicy,针对pod中所有容器生效。

  • Always,除了 Running 状态,其他状态总是重启,默认值。
  • OnFailure,失败了才重启。
  • Never,从不重启。

实验1:验证pod中含有单个容器重启策略。

更改pod重启策略,直接apply会报错,需要删除重建。

第一个yaml验证Always/OnFailure/Never重启策略

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Always/OnFailure/Never
  containers:
  - name: busybox
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']

第二个yaml验证OnFailure

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: OnFailure
  containers:
  - name: busybox
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

第三个yaml验证 Never 重启策略

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

实验2:验证pod中含有多个容器重启策略。

验证结果:只要有一个容器满足重启策略条件,就会重启。

示例1:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Always/OnFailure/Never
  containers:
  - name: busybox1
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']

使用Always重启策略时,当容器busybox1状态为Completed时,容器busybox2还未创建成功,此时会根据重启策略重启pod。当然也可以将容器的生命周期延长,sleep 5改为sleep 50,运行50s之后还会重启pod。

使用OnFailure/Never重启策略就不会出现这种情况。

示例2:第二个command是错误的。

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Always/OnFailure/Never
  containers:
  - name: busybox1
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: hub.laoma.cloud/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

Always和OnFailure重启策略总是会重启pod;Never重启策略就不会重启pod。

Init Containers

一个pod可以有多个容器在其中运行应用程序,也可以有一个或多个initContainers。initContainers中容器状态必须是complete,containers容器才能运行。

如果pod的initContainers fail,kubernetes根据restartpolicy重启pod,直到initContainers状态为complete。

如果pod中initContainers有多个容器,那么会按顺序创建和执行。按顺序执行的initContainers必须成功才能执行下一个initContainers。所有init全部成功执行完成后,才开始执行pod中常规容器。

使用场景:

1、等待某个服务创建成功。

复制代码
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1

2、等待固定时间后再运行app容器。

复制代码
sleep 60

3、Clone a git repository into a volume

示例1:

bash 复制代码
root@master30:~/pods# vim pod-myapp.yaml
yaml 复制代码
# myservice
---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

# mydb
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

# myapp
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;sleep 3;']
  - name: init-mydb
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;sleep 3;']
  containers:
  - name: myapp-container
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

首先创建2个service,然后创建pod,观察pod状态变化。

示例2:

bash 复制代码
root@master30:~/pods# vim pod-myapp.yaml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  volumes:
  - name: workdir
    emptyDir: {}
  containers:
  - name: myapp-container
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"
  initContainers:
  - name: init-poda
    image: hub.laoma.cloud/library/busybox
    command: ['sh', '-c', 'touch /work-dir/aa.txt && sleep 10']
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"

在app容器中查看文件

bash 复制代码
[root@master30 ~]# kubectl exec myapp-pod -c myapp-container -- ls /xx

pod的状态变化:Init:0/1->PodInitializing->Running

将初始化容器command变更为以下内容再测试:

复制代码
command: ['sh', '-c', 'touchxx /work-dir/aa.txt']

pod的状态变化:

Init:0/1->Init:Error->Init:CrashLoopBackOff,然后Init:Error->Init:CrashLoopBackOff循环。

静态 pod

**问题:**正常情况下,pod 由 master 节点统一管理。那么 master 上的kube-apiserver、kube-scheduler、kube-controller-manager等pod又是由谁来管理的呢?

答案kubelet 服务。master节点上组件以静态Pod方式运行,由本地kubelet进行管理。它们不能通过API Server进行管理,无法与ReplicationController、Deployment或DaemonSet进行关联,并且kubelet也无法对其健康检查。

我们来分析下 kubelet.service 配置。

bash 复制代码
[root@master30 ~]# systemctl status kubelet.service |cat
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Sun 2024-07-14 09:52:08 UTC; 1h 7min ago
       Docs: https://kubernetes.io/docs/
   Main PID: 7489 (kubelet)
      Tasks: 11 (limit: 4557)
     Memory: 39.0M (peak: 39.9M)
        CPU: 1min 45.913s
     CGroup: /system.slice/kubelet.service
             └─7489 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9
......

[root@master30 ~]# cat /usr/lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target

# kubelet.service服务启动参数通过 Drop-In 文件 10-kubeadm.conf 配置
[root@master30 ~]# cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf 
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

# 以下参数定义了kubelet配置文件位置
# KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml
# 该文件中的 staticPodPath 参数定义了一个目录
# kubelet会定期扫描该目录中pod文件,并根据目标中文件变动创建和删除pod
[root@master30 ~]# grep staticPodPath /var/lib/kubelet/config.yaml
staticPodPath: /etc/kubernetes/manifests

[root@master30 ~]# ls -1 /etc/kubernetes/manifests
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml

**注意:**不要修改 staticPodPath 参数配置,否则需要将集群组件4个yaml文件也要复制过去。

我们还可以通过参数 --pod-manifest-path设置,该目录下所有 pod 也是静态 pod。

bash 复制代码
[root@master30 ~]# kubelet --help|grep pod-manifest-path
      --pod-manifest-path string    Path to the directory containing static pod files to run, or the path to a single static pod file. Files starting with dots will be ignored. (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)

思考

1. kubernetes 中 pod 和 container 区别?

答:

容器是运行时概念真正跑应用的进程环境

kubernetes 中 Pod:是 K8s 独有的概念 ,是 K8s 中最小调度、管理、自愈单元,是容器的"外壳 + 运行环境"

  • **一个 Pod 里可以有 1 个或多个容器,**pod中所有容器:
    • 同住一个房间 ,共用网络、存储
    • 一起被调度到同一台机器,一起销毁。
特性 容器 Pod
K8s 最小调度单位 ❌ 不是 ✅ 是
独立 IP ✅ 有 ✅ 有
独立 存储 ✅ 有 ✅ 有
多容器支持 ❌ 不支持 ✅ 天然支持
网络/存储共享 ❌ 不能 ✅ 内部容器可共享
生命周期管理 ❌ 弱 ✅ 完整(重启、自愈)
属于谁 运行时(Docker/containerd) Kubernetes

2. kubernetes 为什么直接管理 pod 而不是容器?

  1. 容器太"原子",不适合直接调度。K8s 需要一个能直接被调度、能独立运行、有完整身份 的对象--Pod
  • 容器:只是一个进程/运行环境(Docker/containerd)。

  • Pod:是容器的封装 + 网络/存储/配置/生命周期的统一抽象 。K8s 调度、扩缩容、自愈、服务发现、监控......全都以 Pod 为单位

  1. Pod 支持"多容器协同"(最关键设计)。

    很多场景必须多个容器一起跑、共享资源

    • 业务容器 + Sidecar(日志、监控、代理)
    • 业务容器 + InitContainer(初始化)
    • 业务容器 + 网络/安全代理容器

    它们需要:

    • 共享 Network Namespace(同一个 IP、端口空间)
    • 共享 Volume
    • 一起调度到同一台机器
  2. Pod 提供统一的生命周期与自愈

    K8s 要做:

    • 重启失败容器
    • 替换崩溃节点上的实例
    • 滚动更新、回滚
    • 扩缩容

    这些行为必须作用在一个稳定、标准、独立的单元上:

    • 如果直接管容器,多容器应用会乱
    • 以 Pod 为单位,管理语义清晰、一致
  3. 解耦底层容器运行时。

    Pod 屏蔽了底层实现:

    • Docker
    • containerd
    • cri-o
    • 其他 CRI 运行时

    K8s 只跟 Pod/CRI 打交道,不绑定某一种容器技术。

3. 解释 pod 中 pause 容器作用

在 Kubernetes 里,每个 Pod 都会自动创建一个 pause 容器(也叫 infra 容器) ,它是 Pod 里第一个启动、最后退出的容器,作用非常关键。

  1. pause 容器是干嘛的?

    pause 容器就是为了"占坑",把 Pod 的网络和命名空间先 hold 住。

  2. 它的 3 个核心作用

    创建并持有 Pod 的 Linux Namespace

    Pod 里所有容器要共享:

    • Network namespace(同一个 IP、端口)
    • PID namespace(可选)
    • IPC namespace

    这些共享空间必须由一个"永远不死"的容器来持有 ,否则共享空间会消失。这个容器就是 pause

    让 Pod 生命周期独立于业务容器

    • 业务容器挂了 → 重启
    • pause 容器不挂 → Pod 就不会消失
    • 网络、IP、存储挂载都能保持不变

    如果没有 pause:业务容器一退出,整个 Pod 的网络就没了,重启也没用。

    实现多容器共享网络

    nginx、业务容器、sidecar 都加入 pause 的 network namespace:

    • 共享同一个 IP
    • 可以用 127.0.0.1 互相访问
    • 端口不能冲突
  3. 超形象比喻

    • pause = 房东
    • Pod = 房子
    • 业务容器 = 租客

    房东(pause)先占好房子(网络/命名空间),租客(业务容器)才能住进来。租客换了一波又一波,房子一直都在。

  4. 一个 Pod 内部结构(最标准)

    bash 复制代码
    Pod
    ├── pause 容器(infra)------ 永远第一个启动
    │    持有:网络命名空间、IP、IPC
    └── 业务容器 1、2、3...
         都加入 pause 的命名空间
  5. 最精炼总结

    pause 容器 = Pod 的基石

    • 只负责 holding namespace
    • 保证 Pod 网络、IP、生命周期稳定

环境清理

bash 复制代码
[root@master30 ~]# kubectl delete ns pods