kubernet+calico二進制安裝及總結

Kubernetes部署了好多遍了,但是每次還是會遇到各種問題。有的是新版本問題,有的是以前踩過的坑。因爲沒有文檔記錄,坑還在那裏,我也還在那裏。

本文是以二進制的方式部署,這樣方便我們發現和解決問題。

環境說明:

角色

組件

IP

備註

Master

kube-apiserver

kube-scheduler

kube-controller-manager

etcd

10.8.8.27


Node1

Docker

Kubelet

kube-proxy

calico-kube-controllers

calico-node

10.8.8.28


Node2

Docker

Kubelet

kube-proxy

calico-node

10.8.8.29


第一部分:kubernetes安裝

1、環境準備

1.1 安裝docker

Kubernetes官網文檔有介紹,當前版本(k8s 1.13)僅支持docker 1.11之後版本,我這裏安裝了docker 1.13版本(傳統的yum安裝:yum install docker)

配置鏡像加速,避免後面下載鏡像的時候出現超時:

在/etc/docker/daemon.json文件中增加以下內容:

{

"registry-mirrors": ["http://68e02ab9.m.daocloud.io"]

}

設置開機啓動:systemctl  enable  docker

然後我們啓動docker:systemctl start docker


1.2 Kubernetes二進制文件準備

kubernetes官網下載需要安裝的版本,我搭建的時候版本是v1.13,所以下載v1.13對應的二進制生成文件,對應連接:https://kubernetes.io/docs/setup/release/notes/#downloads-for-v1-13-0,新版本里面已經不直接提供二進制bin包了,需要手動執行裏面的腳本下載。

解壓下載的文件後,進入cluster目錄,執行get-kube-binaries.sh腳本,會在解壓路徑下形成kubernetes的二進制文件

二進制文件路徑:kubernetes/server/kubernetes/server/bin

管理工具路徑:kubernetes/client/bin

2、配置kubernetes

2.1 創建證書

我最開始並沒有使用安全認證,所有的API接口都是暴露在非安全接口上。這種方式單純部署kubernetes沒有問題,但是在部署calico的時候,會出現各種錯,後面會詳細說

2.1.1 創建apiserver的CA證書

使用openssl生成相關證書

#創建ca私鑰

openssl genrsa   -out ca.key 2048   

#生成ca證書

openssl req   -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj   "/CN=k8s-master"   

#創建apiserver私鑰

openssl genrsa   -out server.key 2048  

#根據配置及私鑰生成apiserver的證書請求文件

openssl req -new   -key server.key -out apiserver.csr -subj "/CN=k8s-master" -config   openssl.cnf    

#利用CA簽發apiserver證書

openssl x509   -req -in apiserver.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out   server.crt -days 365 -extensions v3_req -extfile openssl.cnf    

配置文件(openssl.cnf)內容如下:

[req]

req_extensions = v3_req

distinguished_name = req_distinguished_name

[req_distinguished_name]

[ v3_req ]

basicConstraints = CA:FALSE

keyUsage = nonRepudiation, digitalSignature, keyEncipherment

subjectAltName = @alt_names

[alt_names]

DNS.1 = kubernetes

DNS.2 = kubernetes.default

DNS.3 = kubernetes.default.svc

DNS.4 = kubernetes.default.svc.cluster.local

IP.1 = 10.0.254.1

IP.2 = 10.8.8.27

說明:IP.1 是apisver的cluster IP地址;IP.2 是apisver的宿主主機地址;DNS配置爲kube-apiserver虛擬服務名稱

以上操作會在當前目錄生成:ca.crt  ca.key  ca.srl  server.crt  server.csr  server.key 六個文件


2.1.2 創建kubernet-controller、kubernet-schedule的CA證書

#生成controller私鑰

openssl genrsa   -out controller.key 2048

#生成證書申請文件

openssl req -new   -key controller.key   -out controller.csr -subj "/CN=k8s-master"

#簽發controller證書

openssl x509   -req -in controller.csr -CA ca.crt -CAkey controller.key -CAcreateserial -out   controller.crt -days 365

以上操作會生成:controller.crt  controller.key  controller.csr


2.1.3 創建node1、node2的CA證書

創建方法同2.1.2,只是-subj換成對應的信息,node1換成-subj "/CN=node1",node2換成-subj "/CN=node2"。最終會形成文件:node1.crt  node1.csr  node1.key  node2.crt  node2.csr  node2.key

至此所有的證書都配置完成了,下面開始配置kubernetes的相關組件

2.2 配置相關組件的啓動腳本

2.2.1 在master上配置etcd、kube-apiserver、kube-controller-manager、kube-schedule服務

1)etcd服務

Etcd服務作爲kubernetes集羣的主數據庫,在安裝kubernetes各服務之前需要首先安裝和啓動。從github官網(https://github.com/etcd-io/etcd/releases)下載etcd二進制文件,並將etcd和etcdctl可執行的二進制文件複製到/usr/local/bin目錄下。

設置ETCD服務文件

  • 編輯 /lib/systemd/system/etcd.service

[Unit]

Description=Etcd   Server

After=network.target

[Service]

Type=simple

WorkingDirectory=/var/lib/etcd/

EnvironmentFile=/etc/etcd/etcd.conf

ExecStart=/usr/local/bin/etcd

[Install]

WantedBy=multi-user.target

  • 將服務加入到開機啓動:

systemctl  daemon-reload

systemctl  enable  etcd.service

  • 配置ECTD(單機模式)

編輯/etc/etcd/etcd.conf

ETCD_NAME="etcd1"

ETCD_DATA_DIR="/export/data/etcd"

ETCD_LISTEN_PEER_URLS="http://10.8.8.27:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.8.8.27:2379"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.8.8.27:2380"

ETCD_INITIAL_CLUSTER="etcd1=http://10.8.8.27:2380"

ETCD_INITIAL_CLUSTER_STATE="new"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_ADVERTISE_CLIENT_URLS="http://10.8.8.27:2379"

  • 啓動ETCD

systemctl  start  etcd.service

etcdctl --endpoints=http://10.8.8.27:2379 cluster-health  #檢查etcd啓動狀態


2)kube-apiserver服務

將步驟1.2獲取到的(目錄:kubernetes/server/kubernetes/server/bin下)二進制文件kube-apiserver、kube-controller-manager、kubectl、kube-scheduler複製到/usr/local/bin目下下。

  • 編輯/lib/systemd/system/kube-api.service

[Unit]

Description=Kubernetes API Server

After=etcd.service

Wants=etcd.service

[Service]

EnvironmentFile=/etc/kubernetes/apiserver

ExecStart=/usr/local/bin/kube-apiserver $KUBE_API_ARGS

Restart=on-failure

Type=notify

LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

  • 將服務加入到開機啓動:

systemctl  daemon-reload

systemctl  enable  kube-api.service

  • 配置kube-api

編輯:/etc/kubernetes/apiserver

KUBE_API_ARGS="--storage-backend=etcd3 \

--etcd-servers=http://10.8.8.27:2379 \

--insecure-bind-address=0.0.0.0 \

--secure-port=64 --insecure-port=8080 \ 

--service-cluster-ip-range=10.0.254.0/24 \

--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota \

--logtostderr=false --log-dir=/export/logs/kubernets --v=2 \

--allow-privileged=true \

--tls-private-key-file=/etc/kubernetes/ssl/apiserver/server.key \

--client-ca-file=/etc/kubernetes/ssl/apiserver/ca.crt \

--service-account-key-file=/etc/kubernetes/ssl/apiserver/server.key \

--tls-cert-file=/etc/kubernetes/ssl/apiserver/server.crt"

--service-cluster-ip-range:是集羣虛擬IP地址段範圍;

--admission-control:kubernetes集羣的准入控制設置,各控制模塊以插件的形式一次生效;

--allow-privileged:這個是爲後面的calico準備,因爲calico-node需要以特權模式運行在各node上;

--client-ca-file、--tls-cert-file、--tls-private-key-file:爲剛纔創建的api證書;

--service-account-key-file:這裏稍微提一下serviceaccount,因爲後面calico會創建serviceaccount賬戶,並且它啓動的pod會頻繁使用到。Service Account也是一種一種賬號,但它並不是給集羣的用戶使用的,而是給運行在pod裏的進程使用的。正常情況下,爲了確保kubernetes集羣安全,API server會對客戶端進行身份認證,而pod就是通過serviceaccount認證的,pod在啓動的時候,會根據傳入的serviceaccount(沒有傳入的話使用默認的default),在/var/run/secrets/kubernetes.io/serviceaccount生成ca.crt、namespace、token三個文件,這三個文件就是作爲API Server驗證身份的要素。在master可以通過kubectl get serviceaccount --all-namespaces查看已經創建的Service Account,後面有機會我們還會提到Service Account。


2)kube-controller-manager服務

Kube-controller-manager依賴kube-apiserver服務

  •  編輯/lib/systemd/system/kube-controller-manager.service

[Unit]

Description=Kubernetes   Controller Manager

After=kube-api.service

Wants=kube-api.service

[Service]

EnvironmentFile=/etc/kubernetes/controller-manager

ExecStart=/usr/local/bin/kube-controller-manager   $KUBE_CONTROLLER_MANAGER_ARGS

Restart=on-failure

#Type=notify

LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

我在使用Type=notify的時候,會一直重啓,所以註釋掉


  • 配置/etc/kubernetes/controller-manager

KUBE_CONTROLLER_MANAGER_ARGS="\

--kubeconfig=/etc/kubernetes/kubeconfig.yaml   \

 --master=https://10.8.8.27:6443 \

--logtostderr=false   --log-dir=/export/logs/kubernetes --v=2 \

--service-account-private-key-file=/etc/kubernetes/ssl/apiserver/server.key   \

--root-ca-file=/etc/kubernetes/ssl/apiserver/ca.crt"

對應/etc/kubernetes/kubeconfig.yaml配置如下:

apiVersion:   v1

kind:   Config

users:

 - name: controllermanager

   user:

     client-certificate:   /etc/kubernetes/ssl/kube-controller/controller.crt

     client-key:   /etc/kubernetes/ssl/kube-controller/controller.key

clusters:

 - name: local

   cluster:

     certificate-authority:   /etc/kubernetes/ssl/kube-controller/ca.crt

contexts:

 - context:

     cluster:   local

     user: controllermanager       

   name: my-context

current-context:   my-context

Config可以指定多集羣配置,這裏代表使用my-context的上下文,它包括user:controllermanager、cluster:local的配置

  • 將服務加入到開機啓動:

systemctl  daemon-reload

systemctl  enable  kube-controller-manager.service

3)配置kube-schedule服務

kube-schedule也依賴kube-apisever服務

  • 編輯/lib/systemd/system/kube-scheduler.service

[Unit]

Description=Kubernetes   Scheduler

After=kube-api.service

Wants=kube-api.service

 

[Service]

EnvironmentFile=/etc/kubernetes/scheduler

ExecStart=/usr/local/bin/kube-scheduler   $KUBE_SCHEDULER_ARGS

Restart=on-failure

#Type=notify

LimitNOFILE=65536

 

[Install]

WantedBy=multi-user.target

同樣使用默認的Type

  •  配置/etc/kubernetes/scheduler

KUBE_SCHEDULER_ARGS="   \

--kubeconfig=/etc/kubernetes/kubeconfig.yaml   \

--master=https://10.8.8.27:6443   \

--logtostderr=false   --log-dir=/export/logs/kubernetes --v=2"

--kubeconfig:共用kube-controller-manager配置

  • 將服務加入到開機啓動:

systemctl  daemon-reload

systemctl  enable  kube-scheduler.service

4)啓動kube-apiserver、kube-controller-manager、kube-schedule

systemctl restart kube-api.service

systemctl restart kube-controller-manager.service

systemctl restart kube-scheduler.service


2.2.2 在node1、node2上配置kube-proxy、kubelet服務

同樣將之前獲取的二進制文件kubelet、kube-proxy同步到所有的node的/usr/local/bin目錄下,相應節點的證書也同步到相應目錄下。

配置kubelet服務

  • 編輯/lib/systemd/system/kubelet.service

[Unit]

Description=Kubernetes Kubelet Server

After=docker.service

Requires=docker.service


[Service]

WorkingDirectory=/var/lib/kubelet

EnvironmentFile=/etc/kubernetes/kubelet

ExecStart=/usr/local/bin/kubelet $KUBE_KUBELET_ARGS

Restart=on-failure

Type=notify

LimitNOFILE=65536


[Install]

WantedBy=multi-user.target

  • 配置kubelet

編輯/etc/kubernetes/kubelet

KUBE_KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig.yaml \

--hostname-override=10.8.8.28 \

--logtostderr=false --log-dir=/export/logs/kubernetes --v=2 \

--fail-swap-on=false \

--cgroup-driver=systemd \

--runtime-cgroups=/systemd/system.slice \

--kubelet-cgroups=/systemd/system.slice"

新版本的配置已經不支持—master,需要放在—kubeconfig指定的文件裏;

--pod-infra-container-image:這個選項是指定每個POD裏的基礎容器鏡像,它負責管理POD的network/ipc namespaces,這裏可以指定自己倉庫鏡像(默認是:"k8s.gcr.io/pause:3.1"),也可以通過以下方式下載鏡像,避免returned error: No such image: k8s.gcr.io/pause:3.1"錯誤:

docker pull ibmcom/pause:3.1

docker tag ibmcom/pause:3.1  k8s.gcr.io/pause:3.1

--cgroup-driver=systemd需要和docker保持一致,否則會出現以下錯誤:

failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "system" is different from docker cgroup driver: "systemd"

配置/etc/kubernetes/kubeconfig.yaml內容:

apiVersion: v1

kind: Config

users:

 - name: kubelet

   user:

     client-certificate : /etc/kubernetes/ssl/node1.crt

     client-key: /etc/kubernetes/ssl/node1.key

clusters:

  - cluster:

      server: https://10.8.8.27:6443

      certificate-authority: /etc/kubernetes/ssl/ca.crt

    name: local

contexts:

  - context:

      cluster: local

      user: kubelet

    name: local

current-context: local

client-certificate、client-key:不同的node更換不同的路徑


配置kube-proxy服務

  • 編輯/lib/systemd/system/kube-proxy.service

[Unit]

Description=Kubernetes Kube-Proxy Server

After=network.service

Requires=network.service


[Service]

EnvironmentFile=/etc/kubernetes/proxy

ExecStart=/usr/local/bin/kube-proxy $KUBE_PROXY_ARGS

Restart=on-failure

LimitNOFILE=65536


[Install]

WantedBy=multi-user.target

  • 配置/etc/kubernetes/proxy

KUBE_PROXY_ARGS="--cluster-cidr=10.0.253.0/24 \

--master=https://10.8.8.27:6443 \

--logtostderr=true --log-dir=/export/logs/kubernetes --v=2 \

--hostname-override=10.8.8.28 \

--proxy-mode=iptables \

--kubeconfig=/etc/kubernetes/kubeconfig.yaml"

--proxy-mode:proxy有三種模式,默認爲iptables,新版本也支持ipvs,只是還是測試階段

--kubeconfig:與kubelet共用

3)啓動kubelet、kube-proxy

systemctl daemon-reload

systemctl enable kube-proxy.service

systemctl enable kubelet.service

systemctl start kubelet.service

systemctl start kube-proxy.service

這樣我們的kubernetes就已經安裝完成了


第二部分 Calico安裝

官網已經提供了相應的配置文件,該配置文件定義了所有calico所需資源,直接通過kubectl就可以創建calico-node及calico-kube-controllers。

下載地址:https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/calico.yaml  根據不同的版本,更改v3.5的內容。這裏簡單說明一下配置:

1、配置說明

1)configmap對象配置

kind: ConfigMap

apiVersion: v1

metadata:

  name: calico-config

  namespace: kube-system

data:

  # Configure this with the location of your etcd cluster.

  etcd_endpoints: "http://10.8.8.27:2379"


  # If you're using TLS enabled etcd uncomment the following.

  # You must also populate the Secret below with these files.

  etcd_ca: ""   # "/calico-secrets/etcd-ca"

  etcd_cert: "" # "/calico-secrets/etcd-cert"

  etcd_key: ""  # "/calico-secrets/etcd-key"

  # Typha is disabled.

  typha_service_name: "none"

  # Configure the Calico backend to use.

  calico_backend: "bird"


  # Configure the MTU to use

  veth_mtu: "1440"


  # The CNI network configuration to install on each node.  The special

  # values in this config will be automatically populated.

  cni_network_config: |-

    {

      "name": "k8s-pod-network",

      "cniVersion": "0.3.0",

      "plugins": [

        {

          "type": "calico",

          "log_level": "info",

          "etcd_endpoints": "__ETCD_ENDPOINTS__",

          "etcd_key_file": "__ETCD_KEY_FILE__",

          "etcd_cert_file": "__ETCD_CERT_FILE__",

          "etcd_ca_cert_file": "__ETCD_CA_CERT_FILE__",

          "mtu": __CNI_MTU__,

          "ipam": {

              "type": "calico-ipam"

          },

          "policy": {

              "type": "k8s"

          },

          "kubernetes": {

              "kubeconfig": "__KUBECONFIG_FILEPATH__"

          }

        },

        {

          "type": "portmap",

          "snat": true,

          "capabilities": {"portMappings": true}

        }

      ]

    }

etcd_endpoints:會替換掉變量裏cni_network_config的__ETCD_ENDPOINTS__;

etcd_ca、etcd_cert、etcd_key:同上,會替換相應參數;

cni_network_config: calico-node pod的初始化容器calico-cni利用install-cni.sh,將該參數解析成10-calico.conflist,放到/etc/cni/net.d目錄下,比如我的解析內容如下:

{

  "name":   "k8s-pod-network",

  "cniVersion": "0.3.0",

  "plugins": [

    {

      "type": "calico",

      "log_level":   "info",

      "etcd_endpoints":   "http://10.8.8.27:2379",

      "etcd_key_file":   "",

      "etcd_cert_file":   "",

      "etcd_ca_cert_file":   "",

      "mtu": 1440,

      "ipam": {

          "type":   "calico-ipam"

      },

      "policy": {

          "type": "k8s"

      },

      "kubernetes": {

          "kubeconfig":   "/etc/cni/net.d/calico-kubeconfig"

      }

    },

    {

      "type": "portmap",

      "snat": true,

      "capabilities":   {"portMappings": true}

    }

  ]

}

Kubeconfig:這個配置就是之前提到過的service account發揮作用了,calico-cni的install-cni.sh腳本會讀取/var/run/secrets/kubernetes.io/serviceaccount下的內容,並根據kubelet設置的環境變量(KUBERNETES_SERVICE_PROTOCOL、KUBERNETES_SERVICE_HOST、KUBERNETES_SERVICE_PORT)生成/etc/cni/net.d/calico-kubeconfig配置。這個配置在後面calico-node和calico-kube-controller啓動的時候,訪問kube-apiserver會用到。

2)ServiceAccount對象

apiVersion:   v1

kind:   ServiceAccount

metadata:

  name: calico-node

  namespace: kube-system

創建名爲calica-node的ServiceAccount對象。Pod可以通過指定serviceaccount來說明使用哪個token

3)DaemonSet對象

會在所有node上創建calico-node pod,這個pod包括兩個容器,一個是初始化容器:calico-cni,一個是創建路由和iptables信息的calico-node

CALICO_IPV4POOL_CIDR:這個參數會在ETCD創建一個IPpool;

CALICO_IPV4POOL_IPIP:選擇是否啓動IPIP,默認啓動,off是關閉,關閉的話就是通過BGP協議同步路由。

FELIX_IPINIPENABLED:false是FELIX關閉IPIP

4)Deployment對象

會創建calico-kube-controllers容器。這個容器是監控和並同步network policy、namespaces、pods、nodes、serviceaccount等信息到calico的配置存儲系統。官方文檔建議的是,一個calico-kube-controllers  replicas能管理200個節點,建議總共不超過20個replicas。

2、安裝calico組件

2.1 安裝calico組件

kubectl apply -f calico.yaml  安裝calico組件

2.2 配置kubelet

如果kubernetes要使用calico的話,必須在kubelet的配置加上--network-plugin=cni參數,這樣才能保證kubelet最終能通過cni.go去調用calico的插件。配置完成後,重啓kubelet。

2.3 啓動測試容器,最終會得到如下信息

# kubectl get pods --all-namespaces -o wide

image.png

# kubectl get serviceaccount --all-namespaces

image.png

#kubectl get services --all-namespaces  -o wide

image.png

我列出10.8.8.28上的路由信息,會看到有到192.168.95.139的路由,這個是開啓了IPIP模式

image.png

如果是BGP模式的會出現類似以下情況,路由跑在實際的物理網卡

image.png

路由協議是bird

image.png

可以看到本地啓動了bird客戶端,做BGP路由同步

image.png

iptables上也會看到api server的配置,這裏不一一截圖,大家昨晚之後可以自行查看


3、測試腳本

整個安裝過程花了我很多時間,因爲開始沒做安全,所以遇到各種錯,然後就開始看源碼,找問題,中間也寫了很多calico的測試腳本,我大概梳理一下整個kubernetes+calico之間各組件運行邏輯:

1)IP配置邏輯

image.png


2)IP分配邏輯

這次我沒有認真看calico的IP分配邏輯,所以我把以前經過源碼分析的流程圖拿出來充個數

image.png


下面開始說測試腳本

1、調用calico腳本申請IP資源

這個是模擬cni.go的腳本的,calico執行的時候,會讀取大量的k8s環境變量,以下是環境設置實例:

#!/bin/bash

mkdir -p /var/run/netns/

[ -L /var/run/netns/default ] &&   rm -f /var/run/netns/default

ln -s /var/run/docker/netns/default   /var/run/netns/default

 

export   CNI_ARGS="IgnoreUnknown=1;K8S_POD_NAMESPACE=;K8S_POD_NAME="

#export CNI_ARGS='IgnoreUnknown=1'

export CNI_COMMAND="ADD"

export   CNI_CONTAINERID="7dd0f5009d1e4e6d0289311755e7885b93a5a1aa7e34a066689860df5bf6d763"

export CNI_NETNS="kube-system"

export CNI_IFNAME="eth0"

export CNI_PATH="/opt/cni/bin"

export   CNI_NETNS="/var/run/netns/default"

這裏說一下K8S_POD_NAMESPACE、K8S_POD_NAME(腳本保持空就行)這兩個參數,如果爲空的話,/opt/cni/bin/calico這個腳本是不需要去驗證kube-apiserver的,所以也就不需要serviceaccount,但是如果兩這個不爲空,就需要用到serviceaccount了。也就是/etc/cni/net.d/calico-kubeconfig配置。

開始在沒有配置service account的時候,cni獲取IP出現以下錯誤:

Error adding default_nginx1/83637c6d9fa54573ba62538dcd6b7b5778a7beb4fc1299449e894e488fb3c116   to network calico/k8s-calico-network: invalid configuration: no configuration   has been provided

這其實就是結果返回空的結果。

以下是腳本(calicoctl)內容,go run calicoctl.go 就會出現理想的結果了:

package main

 

import (

          "io/ioutil"

          "bytes"

          "encoding/json"

          "fmt"

          "net"

          "os/exec"

          "reflect"

)

 

type Interface struct {

          Name    string   `json:"name"`

          Mac     string   `json:"mac,omitempty"`

          Sandbox string `json:"sandbox,omitempty"`

}

 

type Result struct {

          CNIVersion string           `json:"cniVersion,omitempty"`

          Interfaces []*Interface     `json:"interfaces,omitempty"`

          IPs        []*IPConfig    `json:"ips,omitempty"`

          //DNS        types.DNS      `json:"dns,omitempty"`

}

 

type IPConfig struct {

          // IP version, either "4" or "6"

          Version string

          // Index into Result structs Interfaces list

          Interface *int

          //Address   string   `json:"address,omitempty"`

          Address   net.IPNet

          Gateway   net.IP

}

 

func NewResult(data []byte) {

          result := &Result{}

          if err := json.Unmarshal(data, result); err != nil {

                fmt.Println(err)

          }

          fmt.Println(result.IPs[0].Version)

}

 

func main() {

          stdout := &bytes.Buffer{}

          stdinData, _ := ioutil.ReadFile("/etc/kubernetes/calico_test.yaml")

          c := exec.Cmd{

                Path:   "/opt/cni/bin/calico",

                Args:   []string{"/opt/cni/bin/calico"},

                Stdin:  bytes.NewBuffer(stdinData),

                Stdout: stdout,

          }

          _ = c.Run()

          result := stdout.Bytes()

          fmt.Println(string(result))

          NewResult(result)

}

對應的/etc/kubernetes/calico_test.yaml內容如下,這個文件對應的是kubelet傳入的stdinData:

{

    "cniVersion": "0.3.0",

    "etcd_ca_cert_file": "",

    "etcd_cert_file": "",

    "etcd_endpoints": "http://10.8.8.27:2379",

    "etcd_key_file": "",

    "ipam": {

      "type": "calico-ipam"

    },

    "kubernetes": {

      "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"

    },

    "log_level": "debug",

    "mtu": 1440,

    "name": "k8s-pod-network",

    "policy": {

      "type": "k8s"

    },

    "type": "calico"

}

2、獲取kubelet cni傳入的參數腳本

編輯calico.go

package main

 

import (

          "io/ioutil"

          "log"

          "os"

)

 

func main() {

          file := "/export/logs/calico/request.log"

          logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND,   0766)

 

          if nil != err {

                panic(err)

          }

          loger := log.New(logFile, "calico",   log.Ldate|log.Ltime|log.Lshortfile)

          loger.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

          Stdin := os.Stdin

          stdinData, err := ioutil.ReadAll(Stdin)

          if err != nil {

                loger.Println("error   reading from stdin:%v",err)

          }

          loger.Println(string(stdinData))

}

這裏講kubelet傳入的請求寫入到了/export/logs/calico/request.log文件中,你也可以直接輸出。最後的結果類似以下內容:

{"cniVersion":"0.3.0","etcd_ca_cert_file":"","etcd_cert_file":"","etcd_endpoints":"http://10.8.8.27:2379","etcd_key_file":"","ipam":{"type":"calico-ipam"},"kubernetes":{"kubeconfig":"/etc/cni/net.d/calico-kubeconfig"},"log_level":"info","mtu":1440,"name":"k8s-calico-network","policy":{"type":"k8s"},"type":"calico"}

編譯並放到/opt/cni/bin目錄下。啓動測試容器就可以看到日誌輸出了


3、獲取ETCD key信息

export ETCDCTL_API=3

etcdctl --endpoints=http://10.8.8.27:2379 get / --prefix --keys-only

4、錯誤介紹

以上其實已經覆蓋了一些錯誤的解決方案,還有一些也在這裏說明一下:

  • x509: certificate is valid for 10.8.8.27, 10.0.254.1, not 10.254.0.1

這裏是因爲kube-apiservre的虛擬IP不在--service-cluster-ip-range配置的範圍之內,解決方案是,刪掉kubernetes的service,讓它重新創建。這樣就不會再出現這個錯了。

  • pod_controller.go:206: Failed to list *v1.Pod: Unauthorized  

這是因爲service account沒有正確配置,導致calico-kube-controllers在向kube-apiserver獲取pod、namespace(namespace_controller.go)、policy(policy_controller.go)、node(node_controller.go)、serviceaaccount(serviceaaccount_controller.go)列表信息時,認證失敗.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章