Heapster啓動的進一步研究

kube-apiserver啓動的時候若是加了以下的參數:git

--admission_control=ServiceAccount

會自動生成一個apiserver.crt和apiserver.key文件,所在目錄是/var/run/kubernetes/,而且程序啓動後會發現,有一個默認的serviceaccount,這種模式下咱們建立的resource都會有一個默認的serviceaccount。github

kube-controller-manager啓動時有這麼兩個參數:golang

--root-ca-file="": If set, this root certificate authority will be included in service account's token secret. This must be a valid PEM-encoded CA bundle.

--service-account-private-key-file="": Filename containing a PEM-encoded private RSA key used to sign service account tokens.

這兩個參數指定了要用哪些文件作token和根證書。若咱們將這兩個參數分別設定值爲apiserver.crt和apiserver.key,那麼啓動後,執行:segmentfault

kubectl get secrets

命令,並詳細地查看該secret能夠看到,該secret中有了兩個data:ca.crt和token,他們分別是apiserver.crt和apiserver.key進行再次加密後的數據。api

這樣,咱們建立一個heapster,heapster所屬的serviceaccount的secret中的兩個data,會被copy到建立出來的容器中,咱們能夠進入該容器找到兩個數據。app

咱們看到kubernetes的源碼中,apiserver的模塊有這麼一個函數,這個函數在啓動apiserver的時候會被調用:less

func GenerateSelfSignedCert(host, certPath, keyPath string, alternateIPs []net.IP, alternateDNS []string) error {
        priv, err := rsa.GenerateKey(rand.Reader, 2048)
        if err != nil {
            return err
        }

        template := x509.Certificate{
            SerialNumber: big.NewInt(1),
            Subject: pkix.Name{
                CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
            },
            NotBefore: time.Now(),
            NotAfter:  time.Now().Add(time.Hour * 24 * 365),

            KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
            ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
            BasicConstraintsValid: true,
        }
        ...
    }

這個函數的功能是建立crt和key,調用這個函數的地方是kubernetes\cmd\kube-apiserver\app\server.go函數

if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" {
                    s.TLSCertFile = path.Join(s.CertDirectory, "apiserver.crt")
                    s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "apiserver.key")
                    // TODO (cjcullen): Is PublicAddress the right address to sign a cert with?
                    alternateIPs := []net.IP{config.ServiceReadWriteIP}
                    alternateDNS := []string{"kubernetes.default.svc", "kubernetes.default", "kubernetes"}
                    // It would be nice to set a fqdn subject alt name, but only the kubelets know, the apiserver is clueless
                    // alternateDNS = append(alternateDNS, "kubernetes.default.svc.CLUSTER.DNS.NAME")
                    if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile, alternateIPs, alternateDNS); err != nil {
                        glog.Errorf("Unable to generate self signed cert: %v", err)
                    } else {
                        glog.Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile)
                    }
                }

經過上一篇能夠知heapster啓動後是要向apiserver作https請求的,因此crt和token必不可少。那爲何咱們不直接拿這邊的crt和key去用呢?this

這篇文章詳細地講了證書生成的相關知識,其中的「添加了SAN的證書生成的過程」和上文源碼中調用生成證書的地方是類似的,可是生成證書的過程當中,hostname部分引用了了一個host@time.Now()做爲/CN。見源代碼中這句:加密

Subject: pkix.Name{
                    CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
                },

這句將生成crt的時候的hostname設置成了host@time,好比vm-56-65@23542343562 這樣的形式,並且每次重啓了apiserver,hostname都會變,容器內部可不知道這個hostname,因此根本無法訪問。

heapster內部會記錄apiserver的幾個common name,即kubernetes源碼中的:

[]string{"kubernetes.default.svc", "kubernetes.default", "kubernetes"}

我認爲這確定是要與kubernetes自生成的crt公用而設計的。 至於爲何不行,等有時間再研究。

相關文章
相關標籤/搜索