了解了linux容器本身的使用,就该考虑如何使用这些技术来“容器化”你的应用。

例如:我们的应用可能是web和mysql组合,也可能是cassandra(Apache开发的分布式的非关系型数据库)这样的分布式系统。而要使用容器把Cassandra运行起来,单单通过docker把它跑起来是没用的。关键是,如何处理好容器之间的编排关系,比如哪些是主,哪些是从,如何进行自动发现和通信,如何做持久化数据存储等等,都是kubernetes考虑剖析的东西。

使用kubeadm部署kubernetes项目

kubeadm是芬兰的一个高中生,在业余时间编写的,看看,牛人都是不受年龄限制的,kubeadm还是比较轻量简单的。

创建部署master节点
kubeadm init

将一个node节点加入到当前集群中
kubeadm join <master 节点的ip和端口>

kubeadm工作原理

首先,在机器上手动安装kubeadm、kubelet、kubectl三个二进制文件。然后,使用kubeadm init部署master节点,最后使用kubeadm join将node加入到集群中。

kubeadm init工作流程

当执行kubeadm init后,kubeadm首先做一系列检查工作,确保这台机器可以部署kubernetes。

  1. linux内核版本是否是3.10以上?
  2. linux cgroups模块是否可用?
  3. 机器的hostname是否标准?在kubernetes项目里,机器的名字以及一切存储在etcd中的api对象,都必须使用标准的DNS命名。
  4. 用户安装的kubeadm和kubelet的版本是否匹配?
  5. 机器上是不是已经安装了kubernetes的二进制文件?
  6. kubernetes的工作端口10250/10251/10252是否已经被占用?
  7. ip、mount等linux指令是否存在?
  8. docker是否已经安装?
  9. ...

然后,kubeadm会生成kubernetes对外提供服务所需的各种证书和对应的目录

生成的证书文件都放在master节点的/etc/kubernetes/pki目录下,最主要的证书文件是ca.crt和ca.key。

用户使用kubectl获取容器日志操作时,需要通过kube-apiserver向kubelet发起请求,这个链接也必须是安全的,kubeadm为这一步生成的是apiserver-kubelet-client.crt文件,对应的私钥是apiserver-kubelet-client.key。

证书生成后,kubeadm会为其他组件生成访问kube-apiserver所需要的配置文件。存放在/etc/kubernetes/xxx.conf:

ls /etc/kubernetes
    admin.conf  controller-manager.conf  kubelet.conf  scheduler.conf

配置文件中记录了master节点的服务器地址、监听端口、证书目录等信息。客户端可以使用这些信息与kube-apiserver建立安全连接。

然后,kubeadm为master组件生成pod配置文件,kube-apiserver、kube-controller-manager、kube-scheduler都会被使用pod的方式部署起来。

在kubeadm中,master组件的yaml文件会被生成在/etc/kubernetes/manifests下,比如kube-apiserver.yaml:

apiVersion: v1
kind: Pod
metadata:
    annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ""
    creationTimestamp: null
    labels:
        component: kube-apiserver
        tier: control-plane
    name: kube-apiserver
    namespace: kube-system
spec:
    containers:
    - command:
        - kube-apiserver
        - --authorization-mode=Node,RBAC
        - --runtime-config=api/all=true
        - --advertise-address=10.168.0.2
        ...
        - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
        - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
        image: k8s.gcr.io/kube-apiserver-amd64:v1.11.1
        imagePullPolicy: IfNotPresent
        livenessProbe:
         ...
        name: kube-apiserver
        resources:
            requests:
                cpu: 250m
        volumeMounts:
        - mountPath: /usr/share/ca-certificates
          name: usr-share-ca-certificates
          readOnly: true
        ...
    hostNetwork: true
    priorityClassName: system-cluster-critical
    volumes:
    - hostPath:
        path: /etc/ca-certificates
        type: DirectoryOrCreate
        name: etc-ca-certificates
     ...

然后,kubeadm为集群生成一个bootstrap token。任何一个节点,只要安装了kubelet和kubeadm,都可以通过kubeadm join以及这个token加入到集群中。

token生成后,kubeadm将ca.crt等重要信息通过configmap的方式存储在etcd中,供后续添加node节点使用,这个configmap的名称是cluster-info。

最后,安装默认插件。kube-proxy和DNS,前者提供整个集群的服务发现,后者提供DNS功能,本质是在客户端启动两个pod。

kubeadm join工作流程

任何一台机器想要成为kubernetes集群中的一个节点,就必须在kube-apiserver上注册。想要连接到apiserver,就必须有证书文件,为了一键安装,不能让用户去master节点手动拷贝。bootstrap token,就扮演着安全验证的角色。只要有了kube-apiserver的地址、端口、证书,kubelet就可以以安全模式连接到apiserver上,这样一个新的节点就部署完成了。

配置kubeadm部署参数

编写kubeadm.yaml文件

apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.0
api:
  advertiseAddress: 192.168.0.102
  bindPort: 6443
  ...
etcd:
  local:
    dataDir: /var/lib/etcd
    image: ""
imageRepository: k8s.gcr.io
kubeProxy:
  config:
    bindAddress: 0.0.0.0
    ...
kubeletConfiguration:
  baseConfig:
    address: 0.0.0.0
    ...
networking:
  dnsDomain: cluster.local
  podSubnet: ""
  serviceSubnet: 10.96.0.0/12
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  ...

可以修改kube-apiserver参数,修改证书文件,修改容器运行时,修改镜像URL等,通过制定这个部署参数配置文件,就能够实现自定义配置参数了。

kubeadm init --config kubeadm.yaml

总结

因为kubeadm目前还无法部署一个高可用的kubernetes集群,etcd、master组件都是单点,导致kubeadm暂时还无法用于生产环境,随着项目的增进,这以后就不会是一个问题了。

另外,如果有部署规模化生产环境的需求,可以使用kops或者saltstack这样更复杂的部署工具。

07-04 15:50