「KUBERNETES-OBJECTS」- Pod | 学习笔记

组成

针对 Pod 网络:Understanding kubernetes networking: pods

性质

Termination of Pods | https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination

启动命令 command 启动参数 args

Define a Command and Arguments for a Container | Kubernetes
How to set multiple commands in one yaml file with Kubernetes? – Stack Overflow

使用 command 定义启动命令,使用 args 定义启动参数。在容器启动后,该参数不能修改。

命令及参数的示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-command-demo
spec:
  containers:
  # 通过 command 及 args 来执行命令
  - name: command-demo-container
    command: ["printenv"]
    args: ["HOSTNAME", "KUBERNETES_PORT"]
  # 针对较长的参数
  - name: long-args
    command:
    - java
    - -jar
    - -Dfoo=1
    - -Dbar=2
    - app.jar

节点选择 nodeSelector

Assign Pods to Nodes | https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/

...
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd
...

镜像拉取策略 imagePullPolicy

IfNotPresent Always Never

拉取私有镜像 imagePullSecrets

第一步、创建访问私有镜像仓库的 Secret 信息:

kubectl create secret generic regcred \
    --from-file=.dockerconfigjson=<path/to/.docker/config.json> \
    --type=kubernetes.io/dockerconfigjson

# 或者,通过命令行指定
kubectl create secret docker-registry regcred  \
    --docker-server=<your-registry-server>     \
    --docker-username=<your-name>              \
    --docker-password=<your-pword>             \
    --docker-email=<your-email>

第二步、在 Pod 中,指定访问该仓库的凭证:

...
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: regcred
...

初始化容器 | spec.initContainers

Init Containers | Kubernetes
Debug Init Containers | Kubernetes

影响 Pod 的启动行为,在某个 POD 启动后再启动另外换一个 POD 实例:

针对详细内容,参考官方手册 https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

向往常一样,创建一个普通的 POD,然后以如下方式定义一个依赖的 POD:

kind: Deployment
apiVersion: apps/v1beta1
metadata:
  name: nginx
spec:
  relicas: 1
  template:
   metadata:
     lable:
       app: nginx
   spec:
     containers:
     - name: webserver
       image: nginx
       ports:
       - containerPort: 80
     initContainers:
     - name: checkabackend
       image: busybox
       # command: ["sh", "-c", "until nslookup..........."]
       command:
       - sh
       - -c
       - |
         cd ...
         ls ...
         ...

查看 initContainers 日志:

kubectl logs "<pod-name>" -c "<init-container-2>"

kubernetes – Init container to be ran only once per deployment – Stack Overflow
当 kubectl apply StatefulSet.yaml 时,只执行一次 initContainers,在后续 Pod 启动时不再执行 initContainers 的?或,是否能够仅运行 initContainers 一次?其为是 Pod 的组成部分,所以 Kubernetes 会为每个 Pod 执行 initContainers 定义。在 Pod 启动时,Kubernetes 会为每个 Pod 执行 initContainers 定义。同理,在 StatefulSet 中,难以实现 initContainers 只执行一次,同理也无法让 Deployment 中 initContainers 只执行一次。需要通过其他手段来实现,例如持久化的文件,如何文件存在,则 initContainers 脚本退出执行。

挂载外部存储 | spec.volumes[]

https://kubernetes.io/docs/concepts/storage/volumes/

nfs | https://kubernetes.io/docs/concepts/storage/volumes/#nfs

该方式挂载的 NFS 无法指定挂载选项,其替代方案如下:
  • You can also mount NFS volumes via PersistentVolumes which do allow you to set mount options.
  • You can either set mount options server-side
  • or use /etc/nfsmount.conf client-side

构建

查看 Pod 日志

Kubectl Reference Docs / top

该笔记将记录:在 Kubernetes 中,查看 Pod 日志及资源占用情况的方法,以及常见问题处理。

通过 kubectl logs 命令查看日志:

# kubectl logs --help
# kubectl logs "pod name" --namespace "your namespace"

# kubectl logs -n kube-system etcd-k8scp-01

# kubectl logs -n kube-system etcd-k8scp-01 -c "container-name"                 # 如果 Pod 包含多个容器,则通过 -c 选项指定容器名;

# kubectl logs -n kube-system etcd-k8scp-01 --previous                          # 查看以停止 Pod 的日志(前个 Pod 实例)
                                                                                # 但,如果容器被清理,则 --previous 则无法成功;

应用

常用 Pod 文件模板

这是我们常用的 Pod 文件的模板,能够根据需要进行剪裁:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-fieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      # 镜像拉取策略:Always、IfNotPresent;
      imagePullPolicy: Always
      # 字段 command 对应镜像的 entrypoint 指令;
      command: [ "sh", "-c"]
      # 字段 args 对应镜像的 CMD 指令;
      args:
      - while true; do
          echo -en '\n';
          printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
          printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
          sleep 10;
        done;
      # 挂载存储
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
      # 限制资源
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"
      # 使用环境变量
      env:
        # 直接定义环境变量
        - name: FOO
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        # 引用定义中的变量作为环境变量
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name

在命令中,使用环境变量

下面的 YAML 文件演示如何使用环境变量:

env:
- name: MESSAGE
  value: "hello world"
command: ["/bin/echo"]
args: ["$(MESSAGE)"]

# 环境变量出现在括号中,这对于在 command 或 args 字段中扩展变量是必需的。

# 以该方式引用环境变量 ≠ 在 Shell 中引用变量
# 该方式由 Kubernetes API 处理,后者由 Shell 解析

执行 Shell 脚本(针对多命令场景)

How to set multiple commands in one yaml file with Kubernetes? – Stack Overflow

下面的 YAML 文件演示如何执行 Shell 脚本:

# 常用简单格式

---
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]

# 或者使用如下形式

---
command: ["/bin/sh", ""]
args:
  - |
    while true
    do
        echo hello
        sleep 10
    done

# 可以根据需要灵活组合

改进

默认 imagePullSecrets 定义

Automatically use secret when pulling from private registry
Kubernetes API Reference / ServiceAccount

在命名空间中,我们希望配置默认 ImagePullSecret 信息,而不需要为每个 Pod 单独添加配置。

# 首先创建 Secret
kubectl create secret docker-registry my-registry-secret \
  --docker-server=<your-registry-server> \
  --docker-username=<your-username> \
  --docker-password=<your-password> \
  --docker-email=<your-email> \
  -n your-namespace

# 然后将 Secret 添加到 default ServiceAccount
kubectl patch serviceaccount default -n your-namespace \
  -p '{"imagePullSecrets": [{"name": "my-registry-secret"}]}'

注意,在 Helm Chart 中,其创建的 Deployment 可能并不使用 default ServiceAccount 资源,所以可能仍旧需要修改 values.yaml 文件。

参考

Expose Pod Information to Containers Through Environment Variables | Kubernetes
Images | Kubernetes
Kubernetes/Concepts/Pods
Pull an Image from a Private Registry | Kubernetes
Managing Resources for Containers | Kubernetes
Labels and Selectors | Kubernetes
docker – Change entrypoint of a k8s Pod, but keep the CMD – Stack Overflow