K8s 的环境安装

安装 k8s

在 centos 7 上 直接运行

yum -y install etcd kubernetes

Kubernetes 依赖 Etcd 服务来维护所有主节点的状态。

系统自带的etcd 版本是3.2.11 kubernetes 的版本是 1.5.2

测试状态

[root@centos ~]# curl 127.0.0.1:8080
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/apps",
    "/apis/apps/v1beta1",
    "/apis/authentication.k8s.io",
    "/apis/authentication.k8s.io/v1beta1",
    "/apis/authorization.k8s.io",
    "/apis/authorization.k8s.io/v1beta1",
    "/apis/autoscaling",
    "/apis/autoscaling/v1",
    "/apis/batch",
    "/apis/batch/v1",
    "/apis/batch/v2alpha1",
    "/apis/certificates.k8s.io",
    "/apis/certificates.k8s.io/v1alpha1",
    "/apis/extensions",
    "/apis/extensions/v1beta1",
    "/apis/policy",
    "/apis/policy/v1beta1",
    "/apis/rbac.authorization.k8s.io",
    "/apis/rbac.authorization.k8s.io/v1alpha1",
    "/apis/storage.k8s.io",
    "/apis/storage.k8s.io/v1beta1",
    "/healthz",
    "/healthz/ping",
    "/healthz/poststarthook/bootstrap-controller",
    "/healthz/poststarthook/extensions/third-party-resources",
    "/healthz/poststarthook/rbac/bootstrap-roles",
    "/logs",
    "/metrics",
    "/swaggerapi/",
    "/ui/",
    "/version"
  ]
  }

修改配置文件

修改

# vim /etc/sysconfig/docker
OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'

修改 k8s apiserver 的配置文件

vim /etc/kubernetes/apiserver

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

中的 ServiceAccount 删掉。

启动服务

1.设置为开机自启动

systemctl enable docker
systemctl enable etcd
systemctl enable kube-apiserver
systemctl enable kube-controller-manager
systemctl enable kube-scheduller
systemctl enable kube-scheduler
systemctl enable kubelet
systemctl enable kube-proxy    

2.启动

systemctl start docker
systemctl start etcd
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduller
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy

至此,一个单机版的k8s 集群就安装好了。

1.查看版本

kubectl version

输出

[root@centos ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"269f928217957e7126dc87e6adfa82242bfe5b1e", GitTreeState:"clean", BuildDate:"2017-07-03T15:31:10Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"269f928217957e7126dc87e6adfa82242bfe5b1e", GitTreeState:"clean", BuildDate:"2017-07-03T15:31:10Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}

2.查看服务

[root@centos ~]# kubectl get service
NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.254.0.1   <none>        443/TCP   12h
[root@centos ~]# kubectl describe services kubernetes
Name:            kubernetes
Namespace:        default
Labels:            component=apiserver
            provider=kubernetes
Selector:        <none>
Type:            ClusterIP
IP:            10.254.0.1
Port:            https    443/TCP
Endpoints:        192.168.10.115:6443
Session Affinity:    ClientIP
No events.

定义 MYSQL RC 配置

我们创建一个 mysql-rc.yaml 的文件,内容如下:

apiVersion: v1 
kind: ReplicationController  # 副本控制器 RC
metadata:
  name: mysql # RC名称,全局唯一
spec:
  replicas: 1 # Pod副本期待数量
  selector:
    app: mysql # 符合目标 Pod拥有此标签
  template:  # 根据此模板创建 Pod 的副本(实例)
    metadata:
      labels:
        app: mysql # Pod 副本拥有的标签,对应 RC 的Selector
    spec:
      containers:  # Pod 内容的定义部分
        - name: mysql #容器的名称
          image: mysql #容器对应的 Docker Image
        ports:
          - containerPort: 3306 # 容器暴露的端口号
        env:  # 注入到容器的环境变量
          - name: MYSQL_ROOT_PASSWORD 
            value: "123456"

说明

  • kind 用来表示此资源对象的类型

  • spec 定义 RC 的相关属性,比如spec.selector 是 RC 的 Pod 标签选择器,即表示监控和管理这些标签的pod实例。

  • replicas = 1 表示只能运行一个mysql Pod 实例,当Pod 数量小于replicas 时,RC会根据spec.template 一节中定义的 Pod 来生成新的Pod实例

  • spec.template.labels 指定了该pod的标签,需要注意这里的app 必须与selector中的app相同,否则无法创建匹配label的pod

创建好 mysql-rc.yaml 文件以后,为了将它发布到 k8s 集群中,我们在 Master 节点执行命令:

kubectl create -f mysql-rc.yaml

提示如下

[root@centos ~]# kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created

提示如下错误请注意yaml 文件的格式是否正确以及配置参数是否输入正确

error: error validating "mysql-rc.yaml": error validating data: kind not set; if you choose to ignore these errors, turn validation off with --validate=false

查看 RC

[root@centos ~]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         0         1m

查看 Pod

[root@centos ~]# kubectl get pods
NAME          READY     STATUS              RESTARTS   AGE
mysql-cvg6c   0/1       ContainerCreating   0          3m

我们看到一个名为 mysql-xxxx的 Pod 实例,这是 k8s 根据 mysql 的这个 RC 文件的定义自动创建的 Pod。 由于其创建需要一些时间,因此我们一开始看到的 Pod 状态是 Pending,待最终完成会被更新为 Running

但是我们这边看到的状态是 ContainerCreating ,我们执行

[root@centos ~]# kubectl describe pod mysql
Name:        mysql-cvg6c
Namespace:    default
Node:        127.0.0.1/127.0.0.1
Start Time:    Sat, 03 Mar 2018 09:22:42 +0800
Labels:        app=mysql
Status:        Pending
IP:
Controllers:    ReplicationController/mysql
Containers:
  mysql:
    Container ID:
    Image:        mysql
    Image ID:
    Port:        3306/TCP
    State:        Waiting
      Reason:        ContainerCreating
    Ready:        False
    Restart Count:    0
    Volume Mounts:    <none>
    Environment Variables:
      MYSQL_ROOT_PASSWORD:    123456
Conditions:
  Type        Status
  Initialized     True
  Ready     False
  PodScheduled     True
No volumes.
QoS Class:    BestEffort
Tolerations:    <none>
Events:
  FirstSeen    LastSeen    Count    From            SubObjectPath    Type        Reason        Message
  ---------    --------    -----    ----            -------------    --------    ------        -------
  8m        8m        1    {default-scheduler }            Normal        Scheduled    Successfully assigned mysql-cvg6c to 127.0.0.1
  8m        3m        6    {kubelet 127.0.0.1}            Warning        FailedSync    Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request.  details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

  8m    12s    35    {kubelet 127.0.0.1}        Warning    FailedSync    Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""

可以看出是镜像下载失败了

Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request.  details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

解决办法:

yum install *rhsm*

因为没有这个文件或目录,这个解决办法,来自这里

然后删除 RC

[root@centos ~]# kubectl delete -f mysql-rc.yaml
replicationcontroller "mysql" deleted

重新创建

[root@centos ~]# kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created
[root@centos ~]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         0         10s
[root@centos ~]# kubectl get pods
NAME          READY     STATUS              RESTARTS   AGE
mysql-7blh0   0/1       ContainerCreating   0          13s
mysql-cvg6c   0/1       Terminating         0          21m

发现还是不行

[root@centos ~]# kubectl describe pods mysql
Name:        mysql-j6vpx
Namespace:    default
Node:        127.0.0.1/127.0.0.1
Start Time:    Sat, 03 Mar 2018 09:51:30 +0800
Labels:        app=mysql
Status:        Pending
IP:
Controllers:    ReplicationController/mysql
Containers:
  mysql:
    Container ID:
    Image:        mysql
    Image ID:
    Port:        3306/TCP
    State:        Waiting
      Reason:        ContainerCreating
    Ready:        False
    Restart Count:    0
    Volume Mounts:    <none>
    Environment Variables:
      MYSQL_ROOT_PASSWORD:    123456
Conditions:
  Type        Status
  Initialized     True
  Ready     False
  PodScheduled     True
No volumes.
QoS Class:    BestEffort
Tolerations:    <none>
Events:
  FirstSeen    LastSeen    Count    From            SubObjectPath        Type        Reason            Message
  ---------    --------    -----    ----            -------------        --------    ------            -------
  59m        59m        1    {default-scheduler }                Normal        Scheduled        Successfully assigned mysql-j6vpx to 127.0.0.1
  32m        32m        1    {kubelet 127.0.0.1}                Warning        MissingClusterDNS    kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  32m        32m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Pulling            pulling image "mysql"
  1m        1m        1    {kubelet 127.0.0.1}                Warning        MissingClusterDNS    kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  59s        59s        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Pulling            pulling image "mysql"

镜像一直在下载,原因是因为gcr.io 被傻逼墙给干了,草他妈的,耽误我折腾一个小时。

解决办法,修改配置文件/etc/sysconfig/docker

OPTIONS='--selinux-enabled=false --registry-mirror=https://olzwzeg2.mirror.aliyuncs.com --insecure-registry gcr.io'

这个是我搜到的镜像加速地址,可以使用

然后重启docker

systemctl restart docker

后再次查看,发现状态是 Running 了。

[root@centos ~]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
mysql-j6vpx   1/1       Running   0          1h

然后 在使用 kubectl describe pods mysql 查看

[root@centos ~]# kubectl describe pods mysql
Name:        mysql-j6vpx
Namespace:    default
Node:        127.0.0.1/127.0.0.1
Start Time:    Sat, 03 Mar 2018 09:51:30 +0800
Labels:        app=mysql
Status:        Running
IP:        172.17.0.2
Controllers:    ReplicationController/mysql
Containers:
  mysql:
    Container ID:    docker://0f1032ef9bd08438996e76c98f7f313b73a07ade76bf6b4b6b5c42de8dcba053
    Image:        mysql
    Image ID:        docker-pullable://docker.io/mysql@sha256:227d5c3f54ee3a70c075b1c3013e72781564000d34fc8c7ec5ec353c5b7ef7fa
    Port:        3306/TCP
    State:        Running
      Started:        Sat, 03 Mar 2018 10:51:26 +0800
    Ready:        True
    Restart Count:    0
    Volume Mounts:    <none>
    Environment Variables:
      MYSQL_ROOT_PASSWORD:    123456
Conditions:
  Type        Status
  Initialized     True
  Ready     True
  PodScheduled     True
No volumes.
QoS Class:    BestEffort
Tolerations:    <none>
Events:
  FirstSeen    LastSeen    Count    From            SubObjectPath        Type        Reason            Message
  ---------    --------    -----    ----            -------------        --------    ------            -------
  33m        33m        1    {kubelet 127.0.0.1}                Warning        MissingClusterDNS    kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  33m        33m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Pulling            pulling image "mysql"
  2m        2m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Pulling            pulling image "mysql"
  2m        1m        2    {kubelet 127.0.0.1}                Warning        MissingClusterDNS    kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  1m        1m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Pulled            Successfully pulled image "mysql"
  1m        1m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Created            Created container with docker id 0f1032ef9bd0; Security:[seccomp=unconfined]
  1m        1m        1    {kubelet 127.0.0.1}    spec.containers{mysql}    Normal        Started            Started container with docker id 0f1032ef9bd0

使用docker ps -a 查看

[root@centos ~]# docker ps -a
CONTAINER ID        IMAGE                                                        COMMAND                  CREATED             STATUS                     PORTS               NAMES
0f1032ef9bd0        mysql                                                        "docker-entrypoint.sh"   6 minutes ago       Up 6 minutes                                   k8s_mysql.f6601b53_mysql-j6vpx_default_64fa560c-1e85-11e8-b481-fa163eee21c2_2999ac54
19334c061120        registry.access.redhat.com/rhel7/pod-infrastructure:latest   "/usr/bin/pod"           7 minutes ago       Up 7 minutes                                   k8s_POD.1d520ba5_mysql-j6vpx_default_64fa560c-1e85-11e8-b481-fa163eee21c2_3a9e5664
f72b01ab8585        registry.access.redhat.com/rhel7/pod-infrastructure:latest   "/usr/bin/pod"           38 minutes ago      Exited (0) 7 minutes ago                       k8s_POD.1d520ba5_mysql-j6vpx_default_64fa560c-1e85-11e8-b481-fa163eee21c2_a7bd20de

节点状态

节点的状态主要是用来描述处于 Running 的节点。当前可用的有 NodeReachable 和 NodeReady。以后可能会增加其他状态。NodeReachable 表示集群可达。NodeReady 表示 kubelet 返回 Status Ok 并且 HTTP 状态检查健康。

定义 MYSQL Service 配置

[root@centos ~]# cat mysql-
mysql-rc.yaml   mysql-svc.yaml
[root@centos ~]# cat mysql-svc.yaml
apiVersion: v1
kind: Service #表明是kubernetes Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql

创建 Service

[root@centos ~]# kubectl create -f mysql-svc.yaml
service "mysql" created

查看刚刚创建的Service

[root@centos ~]# kubectl get svc
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   10.254.0.1      <none>        443/TCP    13h
mysql        10.254.248.63   <none>        3306/TCP   1m

注意 Mysql 已经被分配了一个 10.254.248.63 的IP,我们可以通过 CLUSTER-IP+PORT的方式访问

[root@centos ~]# telnet 10.254.248.63 3306
Trying 10.254.248.63...
Connected to 10.254.248.63.
Escape character is '^]'.
J
5.7.21[8e-7}H8e;-bigi3mysql_native_password

定义 Tomcat RC 配置

创建Tomcat,创建一个 RC 文件 myweb-rc.yaml,内容如下

kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 5
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: kubeguide/tomcat-app:v1
        ports:
        -containerPort: 8080
        env:
        #此处如果在未安装域名解析的情况下,会无法将mysql对应的IP解析到env环境变量中,因此先注释掉!
        # - name: MYSQL_SERVICE_HOST 
        #  value: 'mysql'
        - name: MYSQL_SERVICE_PORT
          value: '3306'       

执行

kubectl create -f myweb-rc.yaml

查看 pods

[root@centos ~]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
mysql-j6vpx   1/1       Running   0          10h
myweb-2bswt   1/1       Running   0          1m
myweb-5wq91   1/1       Running   0          1m
myweb-67j9n   1/1       Running   0          1m
myweb-r74qq   1/1       Running   0          1m
myweb-svz49   1/1       Running   0          1m

定义 Tomcat Service 配置

然后继续创建 myweb-svc.yaml,内容如下

apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  type: NodePort
  ports:
  - port: 8080 # 容器端口
    nodePort: 30001 # 外网映射的端口,可以通过30001 访问容器的8080端口
  selector:
    app: myweb  

创建 Service

[root@centos ~]# kubectl create -f myweb-svc.yaml
service "myweb" created    

查看 Service

[root@centos ~]# kubectl get services
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   10.254.0.1      <none>        443/TCP          22h
mysql        10.254.248.63   <none>        3306/TCP         9h
myweb        10.254.193.35   <nodes>       8080:30001/TCP   32s

删除 rc

[root@centos ~]# kubectl delete -f myweb-rc.yaml

查看 rc

[root@centos ~]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         1         11h
myweb     5         5         0         4s

访问,需要防火墙放行 30001 端口