kubernetes下heapster的部署案例

注:本案例在个人部署环境下是可行的,但不保证在全部环境下均可行。我尽量讲得直白而详细,由于我本身也才刚开始接触,已经作过深刻研究的能够浏览,如有什么错误,烦请指正,感激涕零!node

个人环境: K8S1.0.0+flannel+docker1.6的分布式集群。git

这里先不赘述flannel的部署了,之后有时间再写相关的文档。github

1. ServiceAccount与Secret

先讲讲kubernetes的serviceaccount,咱们的服务有时候须要一些带有隐私信息的东西,token,certification file等等,这些东西咱们能够在master上建立,而后在建立pod的时候导入进去。具体能够去看github上的secret.md,那里有具体的例子。golang

咱们执行:web

kubectl get serviceaccount

若是以下:docker

NAME      SECRETS
default   1

那么是正常的(用脚本启动的kubernetes通常会是这样的状况) 而若是是:json

NAME      SECRETS
default   0

这就麻烦了,用脚本启动k8s,启动的时候是会自动建立一个serviceaccount的,而serviceaccount建立出来的时候又会自动建立一个secret做为这个serviceaccount的token。api

咱们在apiserver的启动参数中添加:curl

--admission_control=ServiceAccount

apiserver在启动的时候会本身建立一个key和crt(见/var/run/kubernetes/apiserver.crtapiserver.keytcp

而后在启动./kube-controller-manager 时添加flag:

--service_account_private_key_file=/var/run/kubernetes/apiserver.key

这样启动k8smaster后,咱们就会发现

kubectl get serviceaccount

结果以下:

NAME      SECRETS
default   1

注意,这里可能会启动apiserver失败,或者启动后没有效果,由于没有secrets的serviceaccount会保存在etcd中,因此咱们在正常启动前最好删掉etcd中的旧数据($etcdctl rm --recursive registry)。

正常启动后咱们在这种状态下建立pod,pod中会加入serviceaccount这个字段,即使咱们在建立的json或yaml中不指定,那么它的默认值也会是默认的serviceaccount:default。 而这个serviceaccount的secret就会被导入到pod启动的containers中。 举个例子,咱们在这种状态下建立一个pod,而后执行:

[root@vm-56-65 bin]# kubectl  get pods/imgpod -o yaml

在yaml中会发现:

spec:
  containers:
  - image: registry.hub.gome.com.cn/img_server:1.1
    imagePullPolicy: IfNotPresent
    name: imgpod
    resources:
      limits:
        cpu: 600m
        memory: 1181116006400m
    terminationMessagePath: /dev/termination-log
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-n0i1i
      readOnly: true
  dnsPolicy: ClusterFirst
  nodeName: 10.58.56.62
  restartPolicy: Always
  serviceAccountName: default
  volumes:
  - name: default-token-n0i1i
    secret:
      secretName: default-token-n0i1i

有了serviceaccountName字段,而且volumn装载了一个secret.是的,这个secret:default-token-n0i1i就是咱们default这个serviceaccount下的secret。它被装载到mountPath: /var/run/secrets/kubernetes.io/serviceaccount目录中,咱们若是在slaver上进入相关容器,即可以找到这个目录和相应的token(注:建立这个pod的json中不用指定serviceaccount,也不用写volumn字段去挂载secret,这些都会自动完成的,是否能够手动指定呢?期待大神们的指点)。

为何要先说这些呢? 由于咱们的heapster启动的时候会有这种状况: pod状态为running,可是反复地restart;咱们用webapi查看该pod的日志,发现:

/var/run/secret/kubernetes.io/serviceaccount/token no such file or directory

我认为这是由于heapster在运行时须要向k8smaster作https的链接,可是没有token和证书是不能链接的,heapster的程序找不到token就error并exit了,k8s会再启动之,因而就反复restart。

2.解决Heapster的Https访问问题

以下是我heapster启动的json(一个replicationcontroller)

heaprep.json:
{
    "apiVersion": "v1",
    "kind": "ReplicationController",
    "metadata": {
        "labels": {
            "name": "heapster"
        },
        "name": "monitoring-heapster-controller"
    },
    "spec": {
        "replicas": 1,
        "selector": {
            "name": "heapster"
        },
        "template": {
            "metadata": {
                "labels": {
                    "name": "heapster"
                }
            },
            "spec": {
                "containers": [
                    {
                        "image": "registry.hub.gome.com.cn/kubernetes/heapster:v0.16.0",
                        "name": "heapster",
            "command":[
                "/heapster",
                "--source=kubernetes:'https://kubernetes:443?auth='",
                "--sink=influxdb:http://10.126.53.10:8086"
            ],
            "resources": {
                        "limits":{
                            "cpu":"0.5",
                            "memory":"1.1Gi"
                        }
                },
             "env": [
              {
                "name": "KUBERNETES_SERVICE_HOST",
                "value": "vm-56-65"
              }
            ]
                    }
                ]
            }
        }
    }
}

这里"env"中的环境变量是必需要加的,不然heapster会报错,具体什么错不大记得了,应该是有关10.0.0.1 这个域名的(heapster中的KUBERNETES_SERVICE_HOST变量默认是10.0.0.1)。 *10.0.0.1是k8s集群中master服务的ClusterIP(kubectl get svc 就能够看到),其余slaver是能够经过这个ip:port访问到master服务的。可是由于heapster作的是https的请求,须要crt证书和token。而10.0.0.1不是一个hostname而且没有相关的证书(感受这是heapster最大的一个坑),因此我干脆本身作证书,本身作hosts引导,本身作环境变量。

如今咱们须要一个hostname为vm-56-65的证书,执行这些命令:

openssl genrsa -out ca.key 2048

openssl req -x509 -new -nodes -key ca.key -subj "/CN=abc.com" -days 5000 -out ca.crt

openssl genrsa -out server.key 2048

openssl req -new -key server.key -subj "/CN=vm-56-65" -out server.csr

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000

注意,这里两个 -subj "***"中第二个要写hostname,且强烈建议第一个subj和第二个不要相同(设为相同可能会致使普通的curl https命令认证失败)。具体关于证书的生成,能够参考: http://wangzhezhe.github.io/blog/2015/08/05/httpsandgolang/ 执行这些命令后,会生成一系列文件,将它们一并copy到master的/var/run/kubernetes/中,咱们的master启动要用这些证书文件:

./kube-apiserver --logtostderr=true --log-dir=/var/log/ --v=0 --admission_control=ServiceAccount --etcd_servers=http://127.0.0.1:4001 --insecure_bind_address=0.0.0.0 --insecure_port=8080 --kubelet_port=10250 --service-cluster-ip-range=10.0.0.1/24 --allow_privileged=false   --service-node-port-range='30000-35535'   --secure-port=443    --client_ca_file=/var/run/kubernetes/ca.crt  --tls-private-key-file=/var/run/kubernetes/server.key --tls-cert-file=/var/run/kubernetes/server.crt

这里--secure-port=443 是由于我在heapster访问master时,没有采用内部ClusterIP,而是直接访问物理IP,而端口没有变,因此将master上apiserver的https监听端口修改了以便访问。

这样启动了apiserver后,咱们再从新create pod。 容器启动,咱们进入pod的日志,看到很是多的:

dial tcp: lookup vm-56-65: no such host

进入容器中修改容器里的/etc/hosts,添加一个:

10.58.56.65 vm-56-65

如前文所说,我这里用了物理ip,固然,若是咱们这里配10.0.0.1 也是能够的(若是使用10.0.0.1,api-server启动的时候就不用再添加--secure-port=443了)。 具体怎么进容器、改hosts这里我就不细讲了,你们都懂的~

修改完毕后,再刷新几回pod的日志,会发现,日志慢慢就不更新了(或者该说,不报错了),恭喜你,heapster已经在正常跑了。

不止如此,只要再添加一个token的配置,就能够在任何一台能与10.58.56.65直连的机器上,向apiserver作带认证的https请求。

heapster最大的好处是其抓取的监控数据能够按pod,container,namespace等方式group,这样就能进行监控信息的隐私化,即每一个k8s的用户只能看到本身的应用的资源使用状况,然后台管理者又能看到每台机器的资源使用状况,相似自动扩容之类的功能就有了一个可靠的信息来源。

以上只是我我的在部署过程当中遇到的问题,不能保证这个方案100%可行,我也仍在作进一步的研究,相信heapster还有不少的坑,你们多多交流吧~^_^

相关文章
相关标签/搜索