适合 Kubernetes 初学者的一些实战练习 (六)

简介: 适合 Kubernetes 初学者的一些实战练习 (六)

本系列的前五篇文章:

本实战练习系列的前五文章:

本文继续我们的 Kubernetes 实战练习之旅。

练习1:Kubernetes 里 secret 的使用方法介绍

Kubernetes Secret 解决了密码、token、密钥等敏感数据的配置问题,使用 Secret 可以避免把这些敏感数据以明文的形式暴露到镜像或者 Pod Spec 中。


Secret可以以 Volume 或者环境变量的方式使用。


使用如下命令行创建一个secret:

kubectl create secret generic admin-access --from-file=./username.txt --from-file=./password.txt

输入文件 username.txt 和 password.txt 需要手动创建,里面分别维护用于测试的用户名和密码。

创建成功后,发现secret 的类型为 Opaque

实际上,Kubernetes 的 secret 有三种类型:

1.Service Account:用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中;


2.Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;


3.kubernetes.io/dockerconfigjson :用来存储私有 docker registry 的认证信息。

而我们刚刚创建的 secret 的类型为 Opaque,因此在 kubectl get secrets 的返回结果里,能看到 password 和 username 的值均为 base64 编码:

要在 pod 里消费这个 secret 也很容易,看一个例子:

apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
restartPolicy: Never
volumes:
- name: credentials
secret:
secretName: admin-access
defaultMode: 0440
containers:
- name: secret-container
image: alpine:3.8
command: [ "/bin/sh", "-c", "cat /etc/foo/username.txt /etc/foo/password.txt" ]
volumeMounts:
- name: credentials
mountPath: "/etc/foo"
readOnly: true

创建 pod,自动执行,通过 log 命令查看 pod 的日志:

发现 /bin/sh 命令被执行了,pod mount 的目录 /etc/foo 下的 username.txt 和password.txt 通过 cat 命令显示了输出:

练习2:Kubernetes pod 里一个特殊容器 pause-amd64 的深入剖析

大家在使用 Docker 容器或者 Kubernetes 时, 想必都留意过这个容器:

gcr.io/google_containers/pause-amd64

docker ps的命令返回的结果:

[root@k8s-minion1 kubernetes]# docker ps |grep pause
c3026adee957        gcr.io/google_containers/pause-amd64:3.0           "/pause"                 22 minutes ago      Up 22 minutes                           k8s_POD.d8dbe16c_redis-master-343230949-04glm_default_ce3f60a9-095d-11e7-914b-0a77ecd65f3e_66c108d5
202df18d636e        gcr.io/google_containers/pause-amd64:3.0           "/pause"                 24 hours ago        Up 24 hours                             k8s_POD.d8dbe16c_kube-proxy-js0z0_kube-system_2866cfc2-0891-11e7-914b-0a77ecd65f3e_c8e1a667
072d3414d33a        gcr.io/google_containers/pause-amd64:3.0           "/pause"                 24 hours ago        Up 24 hours                             k8s_POD.d8dbe16c_kube-flannel-ds-tsps5_default_2866e3fb-0891-11e7-914b-0a77ecd65f3e_be4b719e
[root@k8s-minion1 kubernetes]#

Kubernetes 的官网解释:

it’s part of the infrastructure. This container is started first in all Pods to setup the network for the Pod.

大意是:pause-amd64 是 Kubernetes 基础设施的一部分,Kubernetes 管理的所有 pod 里,pause-amd64 容器是第一个启动的,用于实现 Kubernetes 集群里 pod 之间的网络通讯。


对这个特殊容器的技术实现感兴趣的朋友,可以阅读其源代码。


我们查看这个 pause-amd64 镜像的 dockerfile,发现实现很简单,基于一个空白镜像开始:

FROM scratch
ARG ARCH
ADD bin/pause-${ARCH} /pause
ENTRYPOINT ["/pause"]

ARG 指令用于指定在执行 docker build 命令时传递进去的参数。

这个 pause container 是用C语言写的:

在运行的 Kubernetes node 上运行 docker ps,能发现这些 pause container:

pause container 作为 pod 里其他所有 container 的 parent container,主要有两个职责:

  1. 是 pod 里其他容器共享 Linux namespace 的基础
  2. 扮演 PID 1的角色,负责处理僵尸进程

在 Linux 里,当父进程 fork 一个新进程时,子进程会从父进程继承 namespace.


目前 Linux 实现了六种类型的 namespace,每一个 namespace 是包装了一些全局系统资源的抽象集合,这一抽象集合使得在进程的命名空间中可以看到全局系统资源。命名空间的一个总体目标是支持轻量级虚拟化工具 container 的实现,container 机制本身对外提供一组进程,这组进程自己会认为它们就是系统唯一存在的进程。


在 Linux 里,父进程 fork 的子进程会继承父进程的命名空间。与这种行为相反的一个系统命令就是 unshare:

再来聊聊 pause 容器如何处理僵尸进程的。

Pause 容器内其实就运行了一个非常简单的进程,其逻辑可以从前面提到的 Pause github 仓库上找到:

static void sigdown(int signo) {
  psignal(signo, "Shutting down, got signal");
  exit(0);
}
static void sigreap(int signo) {
  while (waitpid(-1, NULL, WNOHANG) > 0);
}
int main() {
  if (getpid() != 1)
    /* Not an error because pause sees use outside of infra containers. */
    fprintf(stderr, "Warning: pause should be the first process\n");
  if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 1;
  if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 2;
  if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
                                             .sa_flags = SA_NOCLDSTOP},
                NULL) < 0)
    return 3;
  for (;;)
    pause();
  fprintf(stderr, "Error: infinite loop terminated\n");
  return 42;
}

这个 c 语言实现的进程,核心代码就28行:

其中第 24 行里一个无限循环 for(;;), 至此大家能看出来 pause 容器名称的由来了吧?

这个无限循环里执行的是一个系统调用 pause:

因此 pause 容器大部分时间都在沉睡,等待有信号将其唤醒。

接收什么信号呢?

一旦收到 SIGCHLD 信号,pause 进程就执行注册的 sigreap 函数。

看下 SIGCHLD 信号的帮助:

SIGCHLD,在一个进程正常终止或者停止时,将 SIGCHLD 信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。

pause 进程注册的信号处理函数 sigreap 里,调用另一个系统调用 waitpid 来获得子进程终止的原因。

总结

本文作为这一系列的第六部分,首先介绍了如何在实际 Kubernetes 项目中使用 Secret 来管理 credentials 和 access token 等敏感信息,以此来避免将其以明文的形式暴露到镜像或者 Pod Spec 中的安全问题。接下来通过源代码分析的形式,剖析了作为 Kubernetes 基础设施之一的 pause-amd64 容器的设计和实现原理。


本教程前五个部分的文章链接接:

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
Kubernetes 监控 调度
Kubernetes Pod调度:从基础到高级实战技巧
Kubernetes Pod调度:从基础到高级实战技巧
198 0
|
5月前
|
Kubernetes Perl 容器
k8s学习-ReplicationController 、ReplicaSet(工作原理、模板、实战)
k8s学习-ReplicationController 、ReplicaSet(工作原理、模板、实战)
40 0
|
5月前
|
Kubernetes Cloud Native 应用服务中间件
云原生|kubernetes 你真的学废了吗---实战k8s 一(jsonpath实战)
云原生|kubernetes 你真的学废了吗---实战k8s 一(jsonpath实战)
67 0
|
4月前
|
存储 Kubernetes 监控
Kubernetes快速进阶与实战:构建可靠的容器化应用平台
Kubernetes快速进阶与实战:构建可靠的容器化应用平台
99 0
|
4月前
|
存储 Kubernetes 安全
Kubernetes Pod配置:从基础到高级实战技巧
Kubernetes Pod配置:从基础到高级实战技巧
154 0
|
5月前
|
Kubernetes Cloud Native 应用服务中间件
云原生|kubernetes 你真的学废了吗---实战k8s 二(命令行创建各类资源)
云原生|kubernetes 你真的学废了吗---实战k8s 二(命令行创建各类资源)
80 1
|
5月前
|
存储 关系型数据库 MySQL
猿创征文|云原生|kubernetes实务---部署MySQL--实战(一)
猿创征文|云原生|kubernetes实务---部署MySQL--实战(一)
53 0
|
5月前
|
Kubernetes Cloud Native 应用服务中间件
【云原生】kubernetes学习之资源(对象)控制器概述---概念和实战(五)
【云原生】kubernetes学习之资源(对象)控制器概述---概念和实战(五)
22 0
|
5月前
|
存储 Kubernetes 安全
k8s学习-持久化存储(Volumes、hostPath、emptyDir、PV、PVC)详解与实战
k8s学习-持久化存储(Volumes、hostPath、emptyDir、PV、PVC)详解与实战
71 0
|
5月前
|
JSON Kubernetes 数据格式
k8s学习-kubectl命令常用选项详解与实战
k8s学习-kubectl命令常用选项详解与实战
61 0

推荐镜像

更多