background

Sometimes into k8s cluster deployment of a pile of service, need to copy a bunch of yaml file, of course there are other ways to deploy, such as pipeline through the establishment of a one way, but it is too slow, although is once and for all, but if just a deployment that can be easily, so it is easy to copy a bunch of yaml files directly, However, if the mirror address in the previous environment is on the Intranet, and the mirror address is placed in another environment, the network fails, you need to change the mirror address

If before the network environment to ali cloud image network address is, is this: long registry-vpc.cn-beijing.aliyuncs.com/xxxx/xxxxx

And now to be deployed to huawei cloud, direct is certainly not to start the yaml file, need to modify this mirror address, changed to: registry.cn-beijing.aliyuncs.com/xxxx/xxxx, change so that you can pull.

So how do you do that?

Call the K8S interface to complete the image replacement

The following code uses the k8S interface to find the services in the current namespace and write them into an array. Then iterate through the array and change the mirror addresses of all pods in the entire namespace

import re
from kubernetes import client, config


class deployServer:
    def __init__(self, kubeconfig) :
        self.kubeconfig = kubeconfig
        config.kube_config.load_kube_config(config_file=self.kubeconfig)
        self._AppsV1Api = client.AppsV1Api()
        # These two are not needed for the time being
        # self._CoreV1Api = client.CoreV1Api()
        # self._ExtensionsV1beta1Api = client.ExtensionsV1beta1Api()

    def list_deploy(self, namespace_name) :
        ":param Namespace_name: specifies the namespace :return: returns a list of Deployments"
        deploySubj = self._AppsV1Api.list_namespaced_deployment(namespace_name)
        return [ subj.metadata.name for subj in deploySubj.items ]

    def patchMultiDeploy(self, namespace_name, newimgdomain) :
        for i in self.list_deploy(namespace_name):
            self.patchDeploy(namespace_name, i, newimgdomain)
            print("{}: {} patch success.".format(namespace_name, i))

    def patchDeploy(self, deploy_namespace, deploy_name, newimgdomain, keyword='vpc') :
        img_addr_rule = r"[^?] [^?] {1,} \. {1,}\.com(\/.*\:.*)"
        img_domain_rule = r"([^?] [^?] {1,} \. {1,}\.com).*\:.*"
        old_deploy = self._AppsV1Api.read_namespaced_deployment(
            name=deploy_name,
            namespace=deploy_namespace,
        )
        old_deploy_container = old_deploy.spec.template.spec.containers
        Iterate through the list of Deployment to get the name of Deployment and its index location
        for i, k in enumerate(old_deploy_container):
            Capture the mirror address other than the domain name
            oldImgAddr = re.findall(img_addr_rule, old_deploy_container[i].image)[0]
            Capture the domain name of the mirror address, you can also not obtain, but obtain more accurate
            oldImgDoamin = re.findall(img_domain_rule, old_deploy_container[i].image)[0]
            Only those that meet the criteria will be replaced
            if keyword inoldImgDoamin: old_deploy_container[i].image = newimgdomain + oldImgAddr self._AppsV1Api.patch_namespaced_deployment( name=deploy_name,  namespace=deploy_namespace, body=old_deploy )return


if __name__ == '__main__':
    kubeconfig = r'kubeconfig/config'
    k8s = deployServer(kubeconfig)
    # specify the namespace where the service resides
    namespace = 'ops-logging'
    # Specify the domain name of the mirror to be replaced
    img = 'docker.elastic.co'
    k8s.patchMultiDeploy(namespace, img)
Copy the code

Note that the Kubeconfig file needs to be specified

Modify the mirror address in the file

The above is the direct tuning interface, through patch to modify, the following is the direct modification yamL file

import os
import re

def modifyImagesFromFile(originpath, src_img, dst_img) :
    _re_rule = r".*image: ([^?] [^?] {1,} \. {1,}\.com).*\:.*"
    if os.path.isdir(originpath):
        filesubj = os.walk(originpath)
        filename = []
        # iterate over all files in the specified path
        for path, _, file in filesubj:
            Create a complete path for all files and write it in a list
            filename = [os.path.join(path, f) for f in file]
        if filename:
            for f in filename:
                with open(f, 'r+', encoding='utf-8') as fr:
                    fr_data = fr.read()
                    replace_list = re.findall(_re_rule, fr_data)
                    if replace_list:
                        for pattern in replace_list:
                            if src_img in pattern:
                                # replace the matched content
                                fr_data = fr_data.replace(pattern, dst_img)
                        fr.seek(0)
                        fr.write(fr_data)
                        print("{} replace success".format(f))
                    else:
                        print("Unknown")
    else:
        print("{} not a directory".format(originpath))


if __name__ == '__main__':
    originpath = R "E:\ project \DEV environment \sg-saas-pro-hbali\gldsg-gvs\deployments"
    dst_img = 'registry.cn-beijing.aliyuncs.com'
    src_img = 'registry-vpc.cn-beijing.aliyuncs.com'
    modifyImagesFromFile(originpath)
Copy the code

Note: You need to put all deployment files in one directory

Conclusion the ha

If all yamL files are down, then directly iterate over all files in the directory, using the re to capture the mirror address, Then replace it and write to the source file.