なかなか、そのままのタイトルですが
なんで、そんなことしたいかと言うと、実行しているPodの中でバックアップ処理を外からさせたいからです。
kubectlが実行出来る環境を構築すれば良いんですが、面倒なので、Pythonだけでなんとかしたかったのですよ
func.py
import sysimport ioimport jsonimport loggingimport yamlimport ocifrom kubernetes import client, configfrom kubernetes.client.rest import ApiExceptionfrom kubernetes.stream import streamfrom fdk import response# Execute command to Pod.def exec_commands(api_instance : client.CoreV1Api, podname, commands, loopwait=10, namespace = 'default' ): result="" name = podname resp = api_instance.read_namespaced_pod(name=name, namespace=namespace) if not resp: raise Exception('not', 'resp') # Calling exec interactively exec_command = ['/bin/sh'] resp = stream(api_instance.connect_get_namespaced_pod_exec, name, namespace, command=exec_command, stderr=True, stdin=True, stdout=True, tty=False, _preload_content=False) max_loop=loopwait loop=0 while resp.is_open(): sout = resp.readline_stdout(timeout=1) if sout is not None : result += (sout + '\n') loop=0 if resp.peek_stderr(): print( resp.read_stderr(), file=sys.stderr) if commands: c = commands.pop(0) resp.write_stdin(c + "\n") loop=0 else: if loop > max_loop : break loop+=1 resp.close() return resultdef handler(ctx, data: io.BytesIO = None): result = "" # OKE Cluster OCID cid = "" apikey = '' podname = '' commands = [] try: # Jsonロード body = json.loads(data.getvalue()) bdata = body.get("data") cid = bdata['clusterid'] apikey = bdata['apikey'] podname = bdata['podname'] for cmd in bdata['commands']: commands.append( cmd ) # Function auth information signer = oci.auth.signers.get_resource_principals_signer() # Build OKE Client ce_client : oci.container_engine.ContainerEngineClient = oci.container_engine.ContainerEngineClient({}, signer=signer) # Build Cluster config res : oci.response.Response = ce_client.create_kubeconfig(cluster_id=cid) kconfig = res.data.text # Cluster config load kubeconfig2 = yaml.load(kconfig,Loader=yaml.FullLoader) config.load_kube_config_from_dict(kubeconfig2) # Set ServiceAccount's token apiclient = config.new_client_from_config_dict(kubeconfig2) apiclient.configuration.api_key['authorization'] = apikey apiclient.configuration.api_key_prefix['authorization'] = 'Bearer' # Build Kubernetes client v1 = client.CoreV1Api(apiclient) result = exec_commands(v1, podname, commands, loopwait=10, namespace = 'default' ) except (Exception, ValueError) as ex: logging.getLogger().info('error: ' + str(ex)) return response.Response( ctx, response_data= "Error:"+str(ex), headers={"Content-Type": "application/text"} ) return response.Response( ctx, response_data= result, headers={"Content-Type": "application/text"} )requirements.txt
fdk>=0.1.66kubernetesocipyyamlこれを fn やら、oci fn なんかで呼びだせば Ok です。
APIGatewayから呼び出せるようにすれば、何かと便利ですね。
oci fn function invoke --function-id ファンクションOCID --file "-" --body '{ "data": { "clusterid" : "クラスタOCID", "apikey" : "サービスアカウントのトークン", "podname" : "ポッド名", "commands" : [コマンド] }}'
サービスアカウントのトークンは、以下を参考にして下さい。
OCI の Functionで、OKE(kubernetes) を制御したい





