Kubernetes安装指南:从物理服务器迈向容器环境
创始人
2025-01-27 19:30:43
0次

目前可供选择的容器管理系统已经相当丰富,其中包括Amazon EC2 Container Service、Rancher以及Kubernetes等等。这里之所以选择Kubernetes,是因为它能够被安装至多种环境当中,而且不会导致大家被单一供应商所锁定。

[[163682]]

多年以来,我一直利用物理服务器处理基础服务,例如Apache、Bind、MySQL以及PHP等。当然,有时候我也会出于成本考量而进行服务器迁移。不过在服务器上托管多个网站时往往导致更新工作更加困难,因为它们分别依赖于不同PHP版本。考虑到这些问题,我通常会继续使用某些服务器以避免由迁移带来的麻烦。相信大家在实际工作中也经常面临这样的场景。

我一直在关注Docker生态系统的发展状况,并且意识到一旦向容器进行迁移,我面临的问题都将得到解决。有鉴于此,我开始将托管于法国的3套Gentoo与迁移至托管于美国的1套Debian以及托管于法国的一套Gentoo。

今天,我将向大家介绍如何利用Kubernetes安装Docker并实现容器管理。

目前可供选择的容器管理系统已经相当丰富,其中包括Amazon EC2 Container Service、Rancher以及Kubernetes等等。这里之所以选择Kubernetes,是因为它能够被安装至多种环境当中,而且不会导致大家被单一供应商所锁定。

安装Docker

第一步非常简单。

在Debian之上安装Docker:

apt-get install docker.io

在Gentoo之上安装Docker:

emerge -v docker

下一步是安装Kubernetes。

安装Kubernetes

如果选择使用Docker简单安装方式,那么无需使用集群,但这也会令大家错失Kubernetes的优势所在。

多Docker环境显然属于最佳选项。该环境会首先使用Docker服务启动etcd与flannel,从而启用共享网络并允许Kubernetes管理并共享其配置。

  1. root@c1:/home/shared# etcdctl member list 
  2.  
  3. eacd7f155934262: name=b5.loopingz.com 
  4.  
  5. peerURLs=http://91.121.82.118:2380 
  6.  
  7. clientURLs=http://91.121.82.118:2379,http://91.121.82.118:4001 
  8.  
  9. 2f0f8b2f17fffe3c: name=c2.loopingz.com 
  10.  
  11. peerURLs=http://198.245.51.134:2380 
  12.  
  13. clientURLs=http://198.245.51.134:2379,http://198.245.51.134:4001 
  14.  
  15. 88314cdfe9bc1797: name=default 
  16.  
  17. peerURLs=http://142.4.214.129:2380 
  18.  
  19. clientURLs=http://142.4.214.129:2379,http://142.4.214.129:4001 

现在大家已经拥有多套不同网络:

0.0.0/16代表Kubernetes服务/负载均衡器

1.0.0/16为集群各节点上的pod创建位置,各pod地址将为10.1.xx.0/24。

  1. flannel.1 Link encap:Ethernet HWaddr c2:67:be:06:2c:11 
  2.  
  3. inet addr:10.1.72.0 Bcast:0.0.0.0 Mask:255.255.0.0 
  4.  
  5. inet6 addr: fe80::c067:beff:fe06:2c11/64 Scope:Link 
  6.  
  7. UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1 
  8.  
  9. RX packets:5412360 errors:0 dropped:0 overruns:0 frame:0 
  10.  
  11. TX packets:4174530 errors:0 dropped:21 overruns:0 carrier:0 
  12.  
  13. collisions:0 txqueuelen:0 
  14.  
  15. RX bytes:1651767659 (1.5 GiB) TX bytes:3453452284 (3.2 GiB) 

安装GlusterFS

根据具体pod配置与节点选择,各容器可被创建至任意集群节点当中。这意味着大家需要在不同节点间进行存储资源共享。在这方面可供选择的方案也很多,包括Amazon EFS(仍处于beta测试)、谷歌Cloud Storage、GlusterFS等等。

GlusterFS是一款开放式共享存储解决方案。它能够以后台程序方式运行并使用UDP端口24007。

安装防火墙规则

为了一次性对全部服务器上的防火墙加以更新,我创建了一套小型shell脚本,旨在监听etcd节点上的变更,并根据规则与集群节点情况更新防火墙。

更新防火墙配置

防火墙通过一个fw.conf文件进行配置,并共享于GlusterFS分卷之上:

  1. #!/bin/sh 
  2.  
  3. MD5_TARGET=`md5sum /home/shared/configs/firewall/fw.conf | awk '{print $1}'` 
  4.  
  5. MD5_NEW=`md5sum fw.conf | awk '{print $1}'` 
  6.  
  7. if [ "$MD5_TARGET" == "$MD5_NEW" ]; then 
  8.  
  9. echo "Not config change" 
  10.  
  11. exit 0 
  12.  
  13. fi 
  14.  
  15. cp fw.conf /home/shared/configs/firewall/ 
  16.  
  17. etcdctl set /cluster/firewall/update $MD5_NEW 

其中curl命令配合?wait=true将在该值被上述脚本所变更时发生超时。在此之后,其会对该主机上的防火墙进行更新:

  1. while : 
  2.  
  3. do 
  4.  
  5. curl -L http://127.0.0.1:4001/v2/keys/cluster/firewall/update?wait=true 
  6.  
  7. NEW_HASH=`etcdctl get /cluster/firewall/update` 
  8.  
  9. if [ "$NEW_HASH" != "$FW_HASH" ]; then 
  10.  
  11. echo "Update the firewall" 
  12.  
  13. source /usr/local/bin/firewall_builder 
  14.  
  15. FW_HASH=$NEW_HASH 
  16.  
  17. fi 
  18.  
  19. done 

安装Docker库

要利用Kubernetes保存容器定义,大家最好建立自己的容器库。

因此,让我们利用Kubernetes部署自己的第一个pod:

其默认格式为YAML,但我个人更倾向于使用JSON。

以下为docker-rc.json文件内容:

  1. { 
  2.  
  3. "apiVersion": "v1", 
  4.  
  5. "kind": "ReplicationController", 
  6.  
  7. "metadata": { 
  8.  
  9. "name": "docker-repository", 
  10.  
  11. "labels": { 
  12.  
  13. "app": "docker-repository", 
  14.  
  15. "version": "v1" 
  16.  
  17. } 
  18.  
  19. }, 
  20.  
  21. "spec": { 
  22.  
  23. "replicas": 1, 
  24.  
  25. "selector": { 
  26.  
  27. "app": "docker-repository", 
  28.  
  29. "version": "v1" 
  30.  
  31. }, 
  32.  
  33. "template": { 
  34.  
  35. "metadata": { 
  36.  
  37. "labels": { 
  38.  
  39. "app": "docker-repository", 
  40.  
  41. "version": "v1" 
  42.  
  43. } 
  44.  
  45. }, 
  46.  
  47. "spec": { 
  48.  
  49. "volumes": [ 
  50.  
  51. { 
  52.  
  53. "name": "config", 
  54.  
  55. "hostPath": { "path": "/home/shared/configs/docker" } 
  56.  
  57. },{ 
  58.  
  59. "name": "data", 
  60.  
  61. "hostPath": { "path": "/home/shared/docker" } 
  62.  
  63. } 
  64.  
  65. ], 
  66.  
  67. "containers": [ 
  68.  
  69. { 
  70.  
  71. "name": "registry", 
  72.  
  73. "image": "registry:2.2.1", 
  74.  
  75. "volumeMounts": [{"name":"config", "mountPath":"/etc/docker/"},{"name":"data", "mountPath": "/var/lib/registry 
  76.  
  77. "}], 
  78.  
  79. "resources": { 
  80.  
  81. "limits": { 
  82.  
  83. "cpu": "100m", 
  84.  
  85. "memory": "50Mi" 
  86.  
  87. }, 
  88.  
  89. "requests": { 
  90.  
  91. "cpu": "100m", 
  92.  
  93. "memory": "50Mi" 
  94.  
  95. } 
  96.  
  97. }, 
  98.  
  99. "ports": [ 
  100.  
  101. { 
  102.  
  103. "containerPort": 5000 
  104.  
  105. } 
  106.  
  107. ] 
  108.  
  109. } 
  110.  
  111. ] 
  112.  
  113. } 
  114.  
  115. } 
  116.  
  117. } 
  118.  
  119. } 

接下来是docker-svc.json文件内容:

  1. { 
  2.  
  3. "apiVersion": "v1", 
  4.  
  5. "kind": "Service", 
  6.  
  7. "metadata": { 
  8.  
  9. "name": "docker-repository", 
  10.  
  11. "labels": { 
  12.  
  13. "app": "docker-repository" 
  14.  
  15. } 
  16.  
  17. }, 
  18.  
  19. "spec": { 
  20.  
  21. "type": "LoadBalancer", 
  22.  
  23. "selector": { 
  24.  
  25. "app": "docker-repository" 
  26.  
  27. }, 
  28.  
  29. "clusterIP": "10.0.0.204", 
  30.  
  31. "ports": [ 
  32.  
  33. { 
  34.  
  35. "protocol": "TCP", 
  36.  
  37. "port": 5000, 
  38.  
  39. "targetPort": 5000 
  40.  
  41. } 
  42.  
  43. ] 
  44.  
  45. } 
  46.  
  47. } 

安装nginx代理

为了对服务器上的各个域进行托管,反向代理自然必不可少。安装nginx非常简单,不过需要注意向其中添加几条header:

在我的示例中,第一台主机将为docker.loopingz.com:

  1. server { 
  2.  
  3. listen 443; 
  4.  
  5. server_name docker.loopingz.com; 
  6.  
  7. access_log /var/log/nginx/docker.loopingz.com_access_log main; 
  8.  
  9. error_log /var/log/nginx/docker.loopingz.com_error_log info; 
  10.  
  11. client_max_body_size 0; 
  12.  
  13. chunked_transfer_encoding on; 
  14.  
  15. location / { 
  16.  
  17. include /etc/nginx/conf.d/dev-auth; 
  18.  
  19. proxy_pass http://10.0.0.204:5000; 
  20.  
  21. proxy_set_header X-Real-IP $remote_addr; 
  22.  
  23. proxy_set_header X-Forwarded-Host $host; 
  24.  
  25. proxy_set_header X-Forwarded-Server $host; 
  26.  
  27. proxy_set_header X-Forwarded-Proto $scheme; 
  28.  
  29. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  30.  
  31. add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always; 
  32.  
  33. } 
  34.  
  35. ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!CAMELLIA; 
  36.  
  37. ssl_prefer_server_ciphers on; 
  38.  
  39. ssl_certificate /etc/letsencrypt/live/docker.loopingz.com/fullchain.pem; 
  40.  
  41. ssl_certificate_key /etc/letsencrypt/live/docker.loopingz.com/privkey.pem; 
  42.  
  43. } 

大家可以从文件中看到,我们使用IP 10.0.0.204作为定义于docker-svc.json文件内的集群IP地址。Kubernetes会将该IP映射至我们的Docker注册表容器处。

我希望能够将nginx部署至全部集群节点当中,从而保证全部节点皆可通过http/https入口指向该集群。因此,我们需要为nginx定义replicationController。

  1. { 
  2.  
  3. "apiVersion": "v1", 
  4.  
  5. "kind": "ReplicationController", 
  6.  
  7. "metadata": { 
  8.  
  9. "name": "nginx", 
  10.  
  11. "labels": { 
  12.  
  13. "app": "nginx", 
  14.  
  15. "version": "v1" 
  16.  
  17. } 
  18.  
  19. }, 
  20.  
  21. "spec": { 
  22.  
  23. "replicas": 3, 
  24.  
  25. "selector": { 
  26.  
  27. "app": "nginx", 
  28.  
  29. "version": "v1" 
  30.  
  31. }, 
  32.  
  33. "template": { 
  34.  
  35. "metadata": { 
  36.  
  37. "labels": { 
  38.  
  39. "app": "nginx", 
  40.  
  41. "version": "v1" 
  42.  
  43. } 
  44.  
  45. }, 
  46.  
  47. "spec": { 
  48.  
  49. "volumes": [ 
  50.  
  51. { 
  52.  
  53. "name": "config", 
  54.  
  55. "hostPath": { "path": "/home/shared/configs/nginx/" } 
  56.  
  57. },{ 
  58.  
  59. "name": "logs", 
  60.  
  61. "hostPath": { "path": "/home/shared/logs/nginx/" } 
  62.  
  63. },{ 
  64.  
  65. "name": "certs", 
  66.  
  67. "hostPath": { "path": "/home/shared/letsencrypt/" } 
  68.  
  69. },{ 
  70.  
  71. "name": "static", 
  72.  
  73. "hostPath": { "path": "/home/shared/nginx/" } 
  74.  
  75. } 
  76.  
  77. ], 
  78.  
  79. "containers": [ 
  80.  
  81. { 
  82.  
  83. "name": "nginx", 
  84.  
  85. "image": "nginx:latest", 
  86.  
  87. "volumeMounts": [{"name": "static", "readOnly": true, "mountPath": "/var/www/"},{"name": "certs", "readOnly": true, "mountPath": "/etc/letsencrypt"}, {"name":"logs", "mountPath":"/var/log/nginx/"},{"name":"config", "readOnly": true, "mountPath":"/etc/nginx/conf.d/"}], 
  88.  
  89. "resources": { 
  90.  
  91. "limits": { 
  92.  
  93. "cpu": "100m", 
  94.  
  95. "memory": "50Mi" 
  96.  
  97. }, 
  98.  
  99. "requests": { 
  100.  
  101. "cpu": "100m", 
  102.  
  103. "memory": "50Mi" 
  104.  
  105. } 
  106.  
  107. }, 
  108.  
  109. "ports": [ 
  110.  
  111. { 
  112.  
  113. "containerPort": 80, 
  114.  
  115. "hostPort": 80 
  116.  
  117. },{ 
  118.  
  119. "containerPort": 443, 
  120.  
  121. "hostPort": 443 
  122.  
  123. } 
  124.  
  125. ] 
  126.  
  127. } 
  128.  
  129. ] 
  130.  
  131. } 
  132.  
  133. } 
  134.  
  135. } 
  136.  
  137. } 

进行加密

为了在全部vhost上启用SSL,我们现在需要利用let’s encrypt以获取为期三个月的免费SSL证书。排序可自动进行,因此全部nginx主机都将在其配置文件中包含以下内容:

  1. location /.well-known/acme-challenge { 
  2.  
  3. add_header "Content-Type:" "application/jose+json" always; 
  4.  
  5. root /etc/nginx/conf.d; 
  6.  
  7. } 

现在大家已经了解了Kubernetes的安装方法——马上着手尝试吧!

原文标题:Installing Kubernetes: Moving From Physical Servers to Containers

 【51CTO.com独家译稿,合作站点转载请注明来源】

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何更省钱? 近期特价热门硒鼓... 如今激光打印设备已经成为商务或企业的绝对主力办公设备,但采购者往往忽视了激光打印设备所用的耗材,相对...