本系列前五篇:本系列实战练习的前五篇:Kubernetes初学者的一些实战练习(一)Kubernetes初学者的一些实战练习(2)一些适合Kubernetes初学者的实战练习(3)一些适合Kubernetes初学者的实战练习(4)一些适合Kubernetes初学者的实战练习(5)本文继续我们的Kubernetes实战练习之旅。Exercise1:介绍如何在Kubernetes中使用secretKubernetesSecret解决了密码、token、key等敏感数据的配置问题。使用Secrets可以避免将这些敏感数据以纯文本形式暴露给镜像或PodSpecs。Secret可以用作Volume或环境变量。使用以下命令行创建秘密:kubectlcreatesecretgenericadmin-access--from-file=./username.txt--from-file=./password.txt输入文件username.txt和password.txt需要手动创建,用于测试的用户名和密码分别维护。创建成功后,发现secret类型为Opaque:其实Kubernetes的secret一共有三种:ServiceAccount:用于访问KubernetesAPI,由Kubernetes自动创建,自动挂载到/run/secrets/Pod的kubernetes。在io/serviceaccount目录下;Opaque:base64编码格式的Secret,用于存储密码、密钥等;kubernetes.io/dockerconfigjson:用于存储私有docker注册表的身份验证信息。我们刚刚创建的secret的类型是Opaque,所以在kubectlgetsecrets返回的结果中,可以看到password和username的值都是base64编码的:在pod中消费这个secret也是很容易的,看一个例子:apiVersion:v1kind:Podmetadata:name:secret-podspec:restartPolicy:Nevervolumes:-name:credentialssecret:secretName:admin-accessdefaultMode:0440containers:-name:secret-containerimage:alpine:3.8command:["/bin/sh","-c","cat/etc/foo/username.txt/etc/foo/password.txt"]volumeMounts:-name:credentialsmountPath:"/etc/foo"readOnly:true创建一个pod,执行通过log命令日志查看pod:发现执行了/bin/sh命令,pod挂载目录/etc/foo下的username.txt和password.txt通过cat命令显示输出:练习2:Kubernetespod中的一个特殊容器pause-amd64深度解析当你使用Docker容器或者Kubernetes的时候,你一定注意到了t他的容器:gcr.io/google_containers/pause-amd64dockerps命令返回的结果:[root@k8s-minion1kubernetes]#dockerps|greppausec3026adee957gcr.io/google_containers/pause-amd64:3.0"/pause"22分钟前向上22英里nutesk8s_POD.d8dbe16c_redis-master-343230949-04glm_default_ce3f60a9-095d-11e7-914b-0a77ecd65f3e_66c108d5202df18d636egcr.io/google_containers/pause-amd64:3.0"/pause"24hoursagoUp24hoursk8s_POD.d8dbe16c_kube-proxy-js0z0_kube-system_2866cfc2-0891-11e7-914b-0a77ecd65f3e_c8e1a667072d3414d33agcr.io/google_containers/pause-amd64:3.0"/pause"24hoursagoUp24hoursk8s_POD.d8dbe16c_kube-flannel-ds-tsps5_default_2866e3fb-0891-11e7-914b-0a77ecd65f3e_be4b719e[root@k8s-minion1kubernetes]#Kubernetes官网解释:是基础设施的一部分。该容器首先在所有Pod中启动,以便为Pod设置网络。大致思路是:pause-amd64是Kubernetes基础设施的一部分,在Kubernetes管理的所有pod中,pause-amd64容器最先启动,用于实现Kubernetes集群中pod之间的网络通信。对这个特殊容器的技术实现感兴趣的朋友可以阅读它的源码。我们查看了这个pause-amd64镜像的dockerfile,发现实现很简单,从一张空白镜像开始:FROMscratchARGARCHADDbin/pause-${ARCH}/pauseENTRYPOINT["/pause"]ARG用于指定执行传入的dockerbuild命令参数。这个暂停容器是用C语言写的:在正在运行的Kubernetes节点上运行dockerps,可以找到这些暂停容器:暂停容器是pod中所有其他容器的父容器,并且有两个主要职责:它是被pod中其他容器共享的Linux命名空间的基础,扮演着PID1的角色,它负责处理僵尸进程。在Linux中,当父进程fork出一个新进程时,子进程会继承父进程的命名空间。目前Linux实现了六种命名空间,每一种命名空间都包装了一些全局系统资源的抽象集合,使得全局系统资源在进程的命名空间中是可见的。命名空间的总体目标是支持轻量级虚拟化工具容器的实现。容器机制本身对外提供了一组进程,而这组进程会认为自己是系统中唯一存在的进程。在Linux中,父进程的fork子进程会继承父进程的命名空间。与这种行为相反的一个系统命令是unshare:让我们来谈谈暂停容器如何处理僵尸进程。实际上,Pause容器中运行着一个非常简单的进程,其逻辑可以从前面提到的Pausegithub仓库中找到:staticvoidsigdown(intsigno){psignal(signo,"Shuttingdown,gotsignal");exit(0);}staticvoidsigreap(intsigno){while(waitpid(-1,NULL,WNOHANG)>0);}intmain(){if(getpid()!=1)/*不是错误,因为pause看到在基础容器之外使用。*/fprintf(stderr,"警告:暂停应该是第一个进程\n");如果(sigaction(SIGINT,&(structsigaction){.sa_handler=sigdown},NULL)<0)返回1;如果(sigaction(SIGTERM,&(structsigaction){.sa_handler=sigdown},NULL)<0)返回2;如果(sigaction(SIGCHLD,&(structsigaction){.sa_handler=sigreap,.sa_flags=SA_NOCLDSTOP},NULL)<0)返回3;对于(;;)暂停();fprintf(stderr,"错误:无限循环终止\n");return42;}这个过程用c语言实现的核心代码只有28行:第24行有一个for(;;)的死循环,可以看到pause的内容设备名称从何而来?在这个无限循环中执行的是一个系统调用pause:所以pause容器大部分时间都在休眠,等待信号唤醒它,接收什么信号?一旦接收到SIGCHLD信号,暂停进程就会执行注册的sigreap函数。查看SIGCHLD信号的帮助:SIGCHLD,当一个进程终止或正常停止时,会向其父进程发送SIGCHLD信号。默认情况下,该信号将被系统忽略。如果父进程想获知其子系统的状态,则应捕获此信号。在pause进程注册的信号处理函数sigreap中,调用了另一个系统调用waitpid,获取子进程终止的原因。将本文总结为本系列的第六部分。首先介绍了在实际Kubernetes项目中如何使用Secret来管理凭证、访问令牌等敏感信息,避免以明文形式暴露给图片或PodSpecs。安全问题。接下来以源码分析的形式,分析了Kubernetes基础设施之一的pause-amd64容器的设计和实现原理。本教程前五部分文章链接:Kubernetes初学者的一些实战练习(一)Kubernetes初学者的一些实战练习(二)Kubernetes初学者的一些实战练习(三)Kubernetes初学者的一些实战练习(四)一些适合Kubernetes初学者的实战练习(五)
