好久沒更新過簡書了磷杏,今天把這個習(xí)慣拾起來吧。
背景
之前自己在公司做了一個平臺怎虫,可以實現(xiàn)自動部署微服務(wù)到測試環(huán)境,但RC文件的配置還是按照生產(chǎn)環(huán)境來的困介,所以有同事提了個需求,就是自動部署完之后自動修改RC文件并重啟蘸际。
開始實施
在自己完成測試工作之后開始分析座哩、設(shè)計、實施的粮彤,大概花了多半天的時間根穷,大部分時間還是在前期分析上,知道怎么弄了后导坟,代碼還是很好寫出來的屿良。
鑒于自己之前對K8S的操作僅在一些命令行上,以這個操作為例惫周,更改RC:kubectl edit rc xxx-rc尘惧,刪除微服務(wù):kubectl delete pod xxx;這種方式去自動化實現(xiàn)其實是不可行的递递,python可以與后臺進(jìn)行交互喷橙,但自動進(jìn)入到vim里面去操作就似乎是不可實現(xiàn)的。
百度了一堆資料后登舞,發(fā)現(xiàn)了一個切入點:官方API
果然有對應(yīng)的API操作:
# prefix為k8s api的前綴贰逾,各公司的應(yīng)該不盡相同吧
# 獲取指定的RC文件信息(Json格式):
rc_by_name = ['GET', prefix + '/api/v1/namespaces/{namespace}/replicationcontrollers/{name}'] # read the specified ReplicationController
# 替換RC
rc_replace_by_name = ['PUT', prefix + '/api/v1/namespaces/{namespace}/replicationcontrollers/{name}'] # replace the specified ReplicationController
# 獲取所有Pod列表信息
pod_list = ['GET', prefix + '/api/v1/pods'] # list or watch objects of kind Pod
# 刪除指定Pod
pod_delete_by_name = ['DELETE', prefix + '/api/v1/namespaces/{namespace}/pods/{name}'] # delete a Pod
看到這幾個API,使這個修改RC并重啟Pod的大致思路想必大家都知道了菠秒。
- 獲取指定RC的信息疙剑;
- 根據(jù)RC信息修改部分字段;
- 調(diào)用replace rc接口践叠;
- 查找所有pod言缤,刪除所有與RC文件想匹配的Pod。
步驟1不用介紹禁灼;
步驟2需要提示下轧简,接口獲取到的RC信息是比較多的,不過大多數(shù)是去改環(huán)境變量匾二,也就是如下部分中的字段:
# resp為獲取到的RC的信息哮独,dict格式
# containers一般為1個拳芙,也有多個的情況
# env_index為環(huán)境變量的索引,獲取到RC信息后看到Json文件就知道什么含義了
resp['spec']['template']['spec']['containers'][0]['env'][env_index]['value']
步驟3中有個小坑皮璧,如果不注意的話會報錯的舟扎,那就是得去除resourceVersion的信息:
resp['metadata'].pop('resourceVersion')
步驟4就不多說了。
光說無碼假把式悴务,整體的執(zhí)行流程見下面的代碼:
import requests
from *** import K8SAPI # 將K8S API集中寫到單獨的一個python文件中了
class K8sOperations:
def __init__(self, master_ip, namespace='default'):
self.master_ip = master_ip
self.namespace = namespace
def replace_rc(self, rc, env_index, name, value):
method, url = K8SAPI.rc_by_name
url = url.format(MASTER_IP=self.master_ip, namespace=self.namespace, name=rc)
resp = requests.request(method, url).json()
resp['metadata'].pop('resourceVersion')
if resp['spec']['template']['spec']['containers'][0]['env'][env_index]['name'] == name:
resp['spec']['template']['spec']['containers'][0]['env'][env_index]['value'] = value
response = requests.put(url=url, json=resp)
if response.status_code == 200:
return True
else:
return False
else:
return 'Index or Name Error'
def get_pods_via_rc(self, rc):
method, url = K8SAPI.pod_list
url = url.format(MASTER_IP=self.master_ip)
pods = requests.request(method, url).json()['items']
pod_list = []
for each in pods:
if rc in each['metadata']['name']:
pod_list.append(each['metadata']['name'])
return pod_list
def delete_pods(self, pod_list):
method, url = K8SAPI.pod_delete_by_name
code_sum = 0
for each in pod_list:
url = url.format(MASTER_IP=self.master_ip, namespace=self.namespace, name=each)
resp = requests.request(method, url)
code_sum += resp.status_code
if code_sum == 200*len(pod_list):
return True
else:
return False
def modify_rc_streamline(self, rc, env_index, name, value):
result = self.replace_rc(rc, env_index, name, value)
if not result:
return result
elif result is not True:
return result
pod_list = self.get_pods_via_rc(rc)
result = self.delete_pods(pod_list)
if result:
return True
else:
return 'RC修改完成但重啟Pod異常'
實現(xiàn)功能的代碼如上睹限,至于怎么寫API,各位看官自有各自的一套風(fēng)格讯檐,這兒就不再贅述了羡疗。
成品
確切的說是半成品,將功能完成并可以自由去使用了别洪,但還沒有去做自動部署完后自動執(zhí)行改RC叨恨,做的話也很容易,就是需要調(diào)研一下詳細(xì)的需求挖垛,因為不同的項目組行為不一樣痒钝,可能有的項目組一個RC需要改幾個地方,有的項目組一次性改多個RC痢毒,需要對所有的項目組做調(diào)查送矩。當(dāng)然把所有的可能性都編寫出來最好,但不會用到的可能性不就是無用功嘛哪替。
直接上圖:
后端是Vue.js栋荸,雖不精通,但能造東西凭舶,我覺得作為測試工程師這就夠了蒸其,至少目前夠了。龐大的技術(shù)體系面前库快,哪能樣樣精通摸袁。如果后期有需要,那就學(xué)它丫的
后記
今晚有點失眠义屏。靠汁。