如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇

前言

在上个章节中,我们介绍了如何使用Azure Container Service Engine部署一个DCOS集群,这篇文章我们主要介绍一下如何使用acs engine在Azure中国区部署一个Kubernetes集群。

Kubernetes简介

Kubernetes是Google开源的容器集群管理系统。它构建于docker技术之上,为容器化的应用提供资源调度、部署运行、服务发现、扩容缩容等整一套功能。下图是一张Kubernetes架构总览:
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第1张图片

操作对象

Kubernetes以RESTful形式开放接口,用户可操作的核心对象有三个:

  • pod:是Kubernetes最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。比如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的pod。

  • service:是pod的路由代理抽象,用于解决pod之间的服务发现问题。因为pod的运行状态可动态变化(比如切换机器了、缩容过程中被终止了等),所以访问端不能以写死IP的方式去访问该pod提供的服务。service的引入旨在保证pod的动态变化对访问端透明,访问端只需要知道service的地址,由service来提供代理。

  • replication controller:是pod的复制抽象,用于解决pod的扩容缩容问题。通常,分布式应用为了性能或高可用性的考虑,需要复制多份资源,并且根据负载情况动态伸缩。通过replication controller,我们可以指定一个应用需要几份复制,Kubernetes将为每份复制创建一个pod,并且保证实际运行pod数量总是与该复制数量相等(例如,当前某个pod宕机时,自动创建新的pod来替换)。

可以看到,service和replication controller只是建立在pod之上的抽象,最终是要作用于pod的,那么它们如何跟pod联系起来呢?这就要引入label的概念:label其实很好理解,就是为pod加上可用于搜索或关联的一组key/value标签,而service和replication controller正是通过label来与pod关联的。如下图所示,有三个pod都有label为”app=backend”,创建service和replication Controller时可以指定同样的label:”app=backend”,再通过label selector机制,就将它们与这三个pod关联起来了。例如,当有其他frontend pod访问该service时,自动会转发到其中的一个backend pod。
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第2张图片

功能组件

如下图所示是官方文档里的集群架构图,一个典型的master/slave模型。
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第3张图片
master运行三个组件:

  • apiserver:作为kubernetes系统的入口,封装了核心对象的增删改查操作,以RESTful接口方式提供给外部客户和内部组件调用。它维护的REST对象将持久化到etcd(一个分布式强一致性的key/value存储)。
  • scheduler:负责集群的资源调度,为新建的pod分配机器。这部分工作分出来变成一个组件,意味着可以很方便地替换成其他的调度器。
  • controller-manager:负责执行各种控制器,目前有两类:
    • endpoint-controller:定期关联service和pod(关联信息由endpoint对象维护),保证service到pod的映射总是最新的。
    • replication-controller:定期关联replication controller和pod,保证replication controller定义的复制数量与实际运行pod的数量总是一致的。

slave(称作minion)运行两个组件:

  • kubelet:负责管控docker容器,如启动/停止、监控运行状态等。它会定期从etcd获取分配到本机的pod,并根据pod信息启动或停止相应的容器。同时,它也会接收apiserver的HTTP请求,汇报pod的运行状态。
  • proxy:负责为pod提供代理。它会定期从etcd获取所有的service,并根据service信息创建代理。当某个客户pod要访问其他pod时,访问请求会经过本机proxy做转发。

了解完kubernetes大致的结构以后,我们就可以开始部署Kubernetes集群了。

部署准备

由于国内外网络情况的差异,默认的acs engine是无法顺利在Azure中国区部署的,我们需要对源码进行少量的修改,将默认对google和docker的依赖组件镜像到国内才能顺利部署。这些修改大体上包含如下几步:

  • 在Azure Active Directory中创建Service Principal,使得kubernetes在Azure上有权限动态创建负载均衡
  • 修改examples/kubernetes.json集群描述文件,配置集群规模
  • 修改pkg/acsengine/azureconst.go文件,让acs engine默认支持中国区
  • 修改parts/kubernetesmastercustomscript.sh脚本,将Active Directory的访问地址指向中国区
  • 修改acs engine源码,将Docker和kubctl的下载链接镜像到国内, 将需要从google访问的Docker镜像改到国内能够访问的地方
  • 重新生成pkg/acsengine/template.go文件
  • 编译acs engine

在Azure Active Directory中创建Service Principal

这个service principal的主要目的是让kubernetes有权限访问Azure,并在其中为kubernetes集群中的service创建对应的负载均衡。
1. 登录Azure经典管理门户,点击Active Directory
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第4张图片
2. 点击选择对应的AD,进入配置主界面
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第5张图片
3. 点击“应用程序”按钮,创建一个新的应用程序
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第6张图片
4. 根据弹出的创建向导,创建对应的应用程序
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第7张图片
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第8张图片
5. 应用创建好以后,点击“配置”按钮,可以看到“客户端ID”已经有了。
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第9张图片
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第10张图片
6. 在“密钥”处,点选“1年”,然后保存,这时密钥就创建好了
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第11张图片

通过以上的步骤,ACS engine中需要的service principal就创建好了,我们需要将这两个字段保存下来,后面的步骤中就会用到。

修改examples/kubernetes.json集群描述文件

{
  "apiVersion": "vlabs",
  "properties": {
    "orchestratorProfile": {
      "orchestratorType":"Kubernetes"
    },
    "masterProfile": {
      "count": 1,
      "dnsPrefix":"test-m01",
      "vmSize":"Standard_D2_v2"
    },
    "agentPoolProfiles": [
      {
        "name":"agentpool1",
        "count": 3,
        "vmSize":"Standard_D2_v2",
        "availabilityProfile":"AvailabilitySet"
      }
    ],
    "linuxProfile": {
      "adminUsername":"azureuser",
      "ssh": {
        "publicKeys": [
          {
           "keyData": "XXXXXXXXXXXXXXXXXX(SSH KEY)" }
        ]
      }
    },
    "servicePrincipalProfile": {
      "servicePrincipalClientID":"(上一步中生成的客户端ID)",
     "servicePrincipalClientSecret": "(上一步中生成的密钥)"
    }
  }
}

标红的地方是我们需要修改的,修改好后保存就可以进行下一步了。

修改pkg/acsengine/azureconst.go文件

默认的acs engine是不支持Azure中国区的,不过这并不影响我们修改它的代码让它满足在其上部署,首先我们在pkg/acsengine/azureconst.go中找到AzureLocations数组,并在其末尾添加中国的两个数据中心:”chinanorth”, “chinaeast”。

var AzureLocations = []string{
                "australiaeast",
                "australiasoutheast",
                ……
                "westeurope",
                "westindia",
                "westus",
                "westus2",
                "chinanorth",
                "chinaeast"
}

另外,中国区的域名后缀和海外的Azure也不太一样,在azureconst.go文件中找到AzureProdFQDNFormat配置项,把它从“%s.%s.cloudapp.azure.com”改成“%s.%s.cloudapp.chinacloudapi.cn”

const(
     AzureProdFQDNFormat ="%s.%s.cloudapp.chinacloudapi.cn"
)

修改parts/kubernetesmastercustomscript.sh脚本

默认的配置会去访问Azure的AD的海外节点“login.windows.net”,我们需要将它修改为访问Azure中国的“login.chinacloudapi.cn”。 在这个脚本中找到如下的代码,并在其中增加cloud: “AzureChinaCloud”配置即可切换过来。

cat<< EOF > "${AZURE_JSON_PATH}"
{
    "cloud":"AzureChinaCloud",
    "tenantId":"${TENANT_ID}",
    "subscriptionId":"${SUBNETSCRIPTION_ID}",
    "aadClientId":"${SERVICE_PRINCIPAL_CLIENT_ID}",
    "aadClientSecret":"${SERVICE_PRINCIPAL_CLIENT_SECRET}",
    "resourceGroup":"${RESOURCE_GROUP}",
    "location":"${LOCATION}",
    "subnetName":"${SUBNET}",
    "securityGroupName":"${NETWORK_SECURITY_GROUP}",
    "vnetName":"${VIRTUAL_NETWORK}",
    "routeTableName":"${ROUTE_TABLE}",
    "primaryAvailabilitySetName":"${PRIMARY_AVAILABILITY_SET}"
}

修改acs engine源码,将Docker和kubctl的下载链接镜像到国内

  • 修改parts/kubernetesmastercustomdata.yml, 找到如下的代码片段:
runcmd:
        - /bin/bash -c "/bin/echoDAEMON_ARGS=--advertise-client-urls ""http://127.0.0.1:2379,http://{{{masterPrivateIp}}}:2379""--listen-client-urls""http://0.0.0.0:2379,http://0.0.0.0:4001"" | tee -a/etc/default/etcd"
        - /usr/bin/curl -sSL --retry 12--retry-delay 10 https://get.docker.com/ > /tmp/install-docker
        - /bin/bash -c "/bin/bash/tmp/install-docker"
        - /usr/bin/curl -sSL --retry 12--retry-delay 10https://storage.googleapis.com/kubernetes-release/release/{{{kubectlVersion}}}/bin/linux/amd64/kubectl> /usr/local/bin/kubectl
        - chmod +x /usr/local/bin/kubectl

将上面的代码修改为:

runcmd:
        - /bin/bash -c "/bin/echoDAEMON_ARGS=--advertise-client-urls""http://127.0.0.1:2379,http://{{{masterPrivateIp}}}:2379""--listen-client-urls ""http://0.0.0.0:2379,http://0.0.0.0:4001""| tee -a /etc/default/etcd"
        - /usr/bin/curl -sSL --retry 12--retry-delay 10 http://tiantiaw-sr01.chinacloudapp.cn/install-docker >/tmp/install-docker
        - /bin/bash -c "/bin/bash/tmp/install-docker"
        - /usr/bin/curl -sSL --retry 12--retry-delay 10 http://tiantiaw-sr01.chinacloudapp.cn/kubectl >/usr/local/bin/kubectl
        - chmod +x /usr/local/bin/kubectl
        - /usr/bin/docker pull /kubernetes/pause-amd64:3.0
        - /usr/bin/docker tag /kubernetes/pause-amd64:3.0gcr.io/google_containers/pause-amd64:3.0

这里的修改主要是将Docker和kubectl的安装路径指向国内的镜像,笔者这里暂时创建了一个nginx服务器,将相关的依赖放到了这里,读者朋友们可以将这些依赖包放到自己的服务器或者CDN上来加快部署过程。

需要留意的一点是kubernetes启动pod的时候需要用到gcr.io/google_containers/pause-amd64这个Docker镜像,我们这里采用一个变通的办法,从友商那里下载一个到kubernetes节点上,然后将它改名成为gcr.io/google_containers/pause-amd64,这样kubernetes的核心服务就都能启动起来了(为了避免广告之嫌,友商名称暂时去掉,感兴趣的朋友可以自行搜索,然后将标红的替换成对应的友商地址就行)。

  • 同理修改parts/kubernetesagentcustomdata.yml,这里就不赘述了。

修改acs engine源码,将需要从google访问的Docker镜像改到国内能够访问的地方

acs engine的kubernetes集群部署时,需要访问几个Docker镜像,笔者将这些镜像列了出来:

"gcr.io/google_containers/heapster:v1.2.0"
"gcr.io/google_containers/addon-resizer:1.6"
"gcr.io/google_containers/kubedns-amd64:1.7"
"gcr.io/google_containers/kube-dnsmasq-amd64:1.3"
"gcr.io/google_containers/exechealthz-amd64:1.2"
"gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2"
"gcr.io/google_containers/kube-addon-manager-amd64:v5.1"
"gcr.io/google_containers/hyperkube-amd64:v1.4.5"

国内访问google是被屏蔽的,所以我们需要将这些镜像替换成国内能够访问的镜像,下面是笔者在友商找到的几个镜像地址(感兴趣的朋友可以根据镜像的名称自行搜索,这里避免广告之嫌就不列出了):


index.xxxcloud.com/google_containers/heapster:v1.2.0-beta.0
index.xxxcloud.com/google_containers/addon-resizer:1.6
index.xxxcloud.com/google_containers/kubedns-amd64:1.7
index.xxxcloud.com/google_containers/kube-dnsmasq-amd64:1.3
index.xxxcloud.com/google_containers/exechealthz-amd64:1.2
index.xxxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.2
index.xxxcloud.com/google_containers/kube-addon-manager-amd64:v5.1
index.xxxcloud.com/google_containers/hyperkube-amd64:v1.4.1

具体的替换方式就简单粗暴了,全局搜索对应的以gcr.io开头的镜像,然后替换成国内的镜像就行。

重新生成pkg/acsengine/template.go文件

parts目录中的任何修改需要生效的话,必须重新生成一下pkg/acsengine/template.go文件,这个文件是通过go-bindata命令将parts里面的所有脚本片段资源打包到一个文件中,具体的修改方式如下 (假设$ACS_HOME是源码根目录):

  1. cd $ACS_HOME
  2. rm -fr pkg/acsengine/templates.go
  3. cd parts
  4. go-bindata -o ../pkg/acsengine/template.go .(如果没有go-bindata命令的话就“go get -u github.com/jteeuwen/go-bindata”来获取。)
  5. 修改源码pkg/acsengine/template.go,将package main改成package acsengine

重新编译acs engine

进入acs engine源码根目录,执行go build,顺利的话就可以看到acs-engine生成了。

部署过程

1.登录Azure中国区
azure login –e AzureChinaCloud
2.设置azurecli的模式为arm
azure config mode arm
3.创建资源组(集群中的所有资源都会在这个资源组中创建)
azure group create--name=""--location="",这里的location可选china north或者china east.
4.部署Kubernetes集群
azure group deployment create--name=""--resource-group=""--template-file="./azuredeploy.json"--parameters-file="./azuredeploy.parameters.json"
5.部署成功后,打开azure门户预览,点选下图中标红的地方,复制masterFQDN。
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第12张图片
6.ssh @远程连接到kubernetes master节点
这里的username就是Kubernetes集群描述文件中的adminUsername,masterFQDN就是上图中红色框中的内容。
7.执行kubectl cluster-info, 如果获取到如下的相应,集群就建立成功了
这里写图片描述
8.执行kubectl get nodes获取集群节点信息
如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇_第13张图片
至此为止,我们就在Azure中国区成功部署kubernetes集群了,我们可以尝试在其上部署一个简单的hello world应用,具体的部署过程网上有很多的案例,这里就不赘述了。

结论

Kubernetes的部署过程相对来说比DCOS复杂一点,不仅涉及到国内镜像的问题,还涉及到很多源码的改动,不过修改好源码后,整个部署过程还是很顺利的。通过acs engine可以将以前需要花很长时间才能部署好的kubernetes集群分分钟就部署好,而且还集成了Azure的负责均衡,可以很方便地将Service暴露给外部使用,极大地减轻了IT运维的负担。笔者目前临时使用了几个文件服务器来实现部署,希望不久的将来acs engine能够官方支持Azure中国,这样我们就能更加便利地享受到微软提供的一站式的容器集群解决方案了。

你可能感兴趣的:(如何使用Azure Container Service Engine在Azure中国区部署容器服务(二):Kubernetes篇)