{"id":528,"date":"2020-01-10T21:52:39","date_gmt":"2020-01-10T13:52:39","guid":{"rendered":"https:\/\/www.myway5.com\/?p=528"},"modified":"2023-07-05T21:35:48","modified_gmt":"2023-07-05T13:35:48","slug":"argo-input-output","status":"publish","type":"post","link":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/","title":{"rendered":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790"},"content":{"rendered":"<h2>\u7b80\u4ecb<\/h2>\n<p>argo\u662f\u4e00\u4e2a\u5de5\u4f5c\u6d41\u7684\u8c03\u5ea6\u5f15\u64ce\uff0c\u652f\u6301 Steps \u548c DAG \u8fd9\u4e24\u79cd\u5de5\u4f5c\u6d41\u3002<\/p>\n<ul>\n<li>Steps: \u662f\u6309\u7167\u6b65\u9aa4\uff0c\u4ece\u524d\u5f80\u540e\u7684\u5de5\u4f5c\u6d41\u8c03\u5ea6\u65b9\u6848\u3002\u5de5\u4f5c\u6d41\u4e2d\u7684\u6bcf\u4e00\u6b65\u90fd\u53ea\u4f9d\u8d56\u4e0a\u4e00\u6b65\u7684\u7ed3\u679c<\/li>\n<li>DAG: \u5168\u79f0\u662f directed acyclic graph\uff0c\u8bd1\u4e3a\u6709\u5411\u65e0\u73af\u56fe\u3002\u4e0e Steps \u7684\u533a\u522b\u5728\u4e8e\u6bcf\u4e00\u6b65\u53ef\u80fd\u4f9d\u8d56\u4e4b\u524d\u7684\u591a\u6b65\u8f93\u51fa\uff0c\u4f46\u662f\u4e0d\u4f1a\u5faa\u73af\u4f9d\u8d56\uff08\u4e5f\u5c31\u662f\u65e0\u73af\uff09<\/li>\n<\/ul>\n<p>\u4e0d\u8bba\u662f\u5728\u4ec0\u4e48\u7c7b\u578b\u7684\u5de5\u4f5c\u6d41\u4e0a\uff0cargo\u90fd\u62bd\u8c61\u51fa\u4e86\u4e24\u79cd\u8f93\u5165\u8f93\u51fa\uff1a<\/p>\n<ul>\n<li>parameters: \u901a\u5e38\u60c5\u51b5\u4e0b\u90fd\u662f\u5b57\u7b26\u4e32\uff0c\u8be5\u5b57\u7b26\u4e32\u53ef\u4ee5\u6765\u6e90\u4e8e\u6807\u51c6\u8f93\u51fa\uff0c\u4e5f\u53ef\u4ee5\u6765\u6e90\u4e8e\u6587\u4ef6\u7684\u5185\u5bb9<\/li>\n<li>artifacts: \u53ef\u4ee5\u7406\u89e3\u6210\u6587\u4ef6<\/li>\n<\/ul>\n<p>\u8f93\u5165\u8f93\u51fa\u662f\u8fde\u63a5\u6574\u4e2a\u5de5\u4f5c\u6d41\u7684\u6838\u5fc3\u3002\u6bcf\u4e00\u6b65\u90fd\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u6b21\u51fd\u6570\u8c03\u7528\u3002\u90a3\u4e48\u5728argo\u4e2d\uff0c\u5b83\u662f\u5982\u4f55\u5b9e\u73b0\u5728\u591a\u6b65\u4e4b\u95f4\u8f93\u5165\u8f93\u51fa\u7684\u4f20\u8f93\u5462\uff1f\u4e0b\u9762\u4f1a\u901a\u8fc7\u6e90\u4ee3\u7801\u8fdb\u884c\u5206\u6790\u3002<\/p>\n<p>\u5728\u770b\u4ee3\u7801\u4e4b\u524d\uff0c\u53ef\u4ee5\u770b\u4e00\u4e2a argo \u7684\u5de5\u4f5c\u6d41\u4e2d\u7684\u4e00\u4e2apod\uff0c\u4e3a\u4e86\u67e5\u770b\u66f4\u65b9\u4fbf\uff0c\u6211\u5220\u9664\u4e00\u4e9b\u4e0d\u9700\u8981\u5173\u6ce8\u7684\u5b57\u6bb5:<\/p>\n<pre><code class=\"line-numbers\">$ kubectl -n workflow describe pods custom-workflow-111-2fw2f-2639432629\n\nName:           custom-workflow-111-2fw2f-2639432629\nNamespace:      workflow\nLabels:         pipeline.starx.com\/nodeID=743\n                workflows.argoproj.io\/completed=true\n                workflows.argoproj.io\/workflow=custom-workflow-111-2fw2f\nAnnotations:    cni.projectcalico.org\/podIP: 10.42.0.83\/32\n                workflows.argoproj.io\/node-name: custom-workflow-111-2fw2f.yolov3-evaluate-743\n                workflows.argoproj.io\/outputs:\n                  {\"result\":...\n                workflows.argoproj.io\/template:\n                  {\"name\":\"yolov3-evaluate-743\",\"inputs\":{\"parameters\":[{\"name\":\"userParam\",\"value\":\"eyJTY29yZVRocmVzaG9sZCI6MC41LCJJb3VfVGhyZXNob2xkIjowLjQ...\nControlled By:  Workflow\/custom-workflow-111-2fw2f\nInit Containers:\n  init:\n    Image:         argoproj\/argoexec:v2.3.0\n    Command:\n      argoexec\n      init\n    Environment:\n      ARGO_POD_NAME:  custom-workflow-111-2fw2f-2639432629 (v1:metadata.name)\n    Mounts:\n      \/argo\/inputs\/artifacts from input-artifacts (rw)\n      \/argo\/podmetadata from podmetadata (rw)\n      \/argo\/staging from argo-staging (rw)\n      \/var\/run\/secrets\/kubernetes.io\/serviceaccount from default-token-lfk5b (ro)\nContainers:\n  wait:\n    Image:         argoproj\/argoexec:v2.3.0\n    Command:\n      argoexec\n      wait\n    Environment:\n      ARGO_POD_NAME:  custom-workflow-111-2fw2f-2639432629 (v1:metadata.name)\n    Mounts:\n      \/argo\/podmetadata from podmetadata (rw)\n      \/mainctrfs\/argo\/staging from argo-staging (rw)\n      \/mainctrfs\/tmp\/artifacts\/artifact-input0 from input-artifacts (rw,path=\"artifact0\")\n      \/mainctrfs\/tmp\/artifacts\/artifact-input1 from input-artifacts (rw,path=\"artifact1\")\n      \/var\/run\/docker.sock from docker-sock (ro)\n      \/var\/run\/secrets\/kubernetes.io\/serviceaccount from default-token-lfk5b (ro)\n  main:\n    Image:         registry.cn-shanghai.aliyuncs.com\/xinhuodev\/wt:0.4\n    Command:\n      sh\n    Args:\n      \/argo\/staging\/script\n    Mounts:\n      \/argo\/staging from argo-staging (rw)\n      \/tmp\/artifacts\/artifact-input0 from input-artifacts (rw,path=\"artifact0\")\n      \/tmp\/artifacts\/artifact-input1 from input-artifacts (rw,path=\"artifact1\")\nVolumes:\n  podmetadata:\n    Type:  DownwardAPI (a volume populated by information about the pod)\n    Items:\n      metadata.annotations -&gt; annotations\n  docker-sock:\n    Type:          HostPath (bare host directory volume)\n    Path:          \/var\/run\/docker.sock\n    HostPathType:  Socket\n  input-artifacts:\n    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)\n    Medium:     \n    SizeLimit:  &lt;unset&gt;\n  argo-staging:\n    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)\n    Medium:     \n    SizeLimit:  &lt;unset&gt;\n  default-token-lfk5b:\n    Type:        Secret (a volume populated by a Secret)\n    SecretName:  default-token-lfk5b\n    Optional:    false\n<\/code><\/pre>\n<p>\u6211\u4eec\u9700\u8981\u5173\u6ce8\u7684\u4fe1\u606f\u6709\uff1a<\/p>\n<ul>\n<li>Pod \u7684 Annotations<\/li>\n<li>Init Containers \u542f\u52a8\u7684\u521d\u59cb\u5316\u5bb9\u5668<\/li>\n<li>Containers \u4e2d\u7684 wait \u5bb9\u5668\u548c main \u5bb9\u5668<\/li>\n<li>Pod \u7684 Volumes \u548c\u6bcf\u4e2a\u5bb9\u5668\u7684 Mounts<\/li>\n<\/ul>\n<h2>Init \u5bb9\u5668<\/h2>\n<p>argo \u521b\u5efa\u7684 Pod \u7684\u521d\u59cb\u5316\u5bb9\u5668\u6267\u884c\u4e86 <code>argoexec init<\/code> \u547d\u4ee4\uff0c\u4ece\u540d\u5b57\u4e0a\u53ef\u4ee5\u731c\u6d4b\u51fa\uff0c\u8fd9\u4e2a\u5bb9\u5668\u8d1f\u8d23\u521d\u59cb\u5316 Pod \u4e2d\u7684\u73af\u5883\uff0c\u6bd4\u5982\u83b7\u53d6\u6765\u4e0a\u4e00\u6b65\u7684\u8f93\u5165\u7b49\u7b49\uff0c\u5bf9\u5e94\u7684\u4ee3\u7801\u662f <code>cmd\/argoexec\/commands\/init.go<\/code>\uff0c \u6211\u4eec\u7684\u5206\u6790\u4e5f\u4ece\u8fd9\u91cc\u5f00\u59cb\u3002\u5728\u6267\u884c <code>argo exec init<\/code>\u4e4b\u540e\uff0c\u7b2c\u4e00\u4e2a\u8c03\u7528\u7684\u51fd\u6570\u5e94\u8be5\u662f<code>loadArtifacts()<\/code>\u3002\u8fd9\u4e2a\u65b9\u6cd5\u4e2d\u505a\u4e86\u4e09\u4ef6\u4e8b: <code>initExecutor()<\/code>\u3001<code>wfExecutor.StageFiles()<\/code>\u3001<code>wfExecutor.LoadArtifacts()<\/code><\/p>\n<p><strong>initExecutor<\/strong>:<\/p>\n<p>initExecutor \u7684\u4ee3\u7801\u5982\u4e0b\uff08\u5220\u9664\u4e86\u4e0d\u91cd\u8981\u7684\u4ee3\u7801\uff09\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">func initExecutor() *executor.WorkflowExecutor {\n    tmpl, err := executor.LoadTemplate(podAnnotationsPath)\n\n    var cre executor.ContainerRuntimeExecutor\n    switch os.Getenv(common.EnvVarContainerRuntimeExecutor) {\n    case common.ContainerRuntimeExecutorK8sAPI:\n        cre, err = k8sapi.NewK8sAPIExecutor(clientset, config, podName, namespace)\n    case common.ContainerRuntimeExecutorKubelet:\n        cre, err = kubelet.NewKubeletExecutor()\n    case common.ContainerRuntimeExecutorPNS:\n        cre, err = pns.NewPNSExecutor(clientset, podName, namespace, tmpl.Outputs.HasOutputs())\n    default:\n        cre, err = docker.NewDockerExecutor()\n    }\n\n    wfExecutor := executor.NewExecutor(clientset, podName, namespace, podAnnotationsPath, cre, *tmpl)\n    yamlBytes, _ := json.Marshal(&amp;wfExecutor.Template)\n    return &amp;wfExecutor\n}\n<\/code><\/pre>\n<p>\u4ece <code>podAnnotationsPath<\/code>\u52a0\u8f7d\u6a21\u677f\uff0c\u8fd9\u4e2a\u6a21\u677f\u5176\u5b9e\u5c31\u662f Argo \u4e2d\u5355\u6b65\u7684\u6267\u884c\u6a21\u677f\uff0c\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5b83\u7684\u503c\u662f <code>\/argo\/podmetadata\/annotations<\/code>\uff0c\u8fd9\u6b63\u597d\u662f <code>init<\/code> \u5bb9\u5668\u7684\u6302\u8f7d\uff0c\u800c\u8fd9\u4e2a\u6302\u8f7d\u5bf9\u5e94\u7684\u5377\u662f\uff1a<\/p>\n<pre><code class=\"line-numbers\"> podmetadata:\n    Type:  DownwardAPI (a volume populated by information about the pod)\n    Items:\n      metadata.annotations -&gt; annotations\n<\/code><\/pre>\n<p>\u8fd9\u91cc\u7684 <code>DownwardAPI<\/code> \u4e5f\u89e3\u91ca\u4e00\u4e0b\uff0c\u5b83\u662f\u4e00\u79cd volume \u7684\u7c7b\u578b\uff0c\u53ef\u4ee5\u5c06 Pod \u548c Container \u7684\u5b57\u6bb5\u901a\u8fc7\u6302\u8f7d\u6587\u4ef6\u7684\u65b9\u5f0f\u63d0\u4f9b\u7ed9\u5bb9\u5668\u5185\u7684\u8fdb\u7a0b\u65b9\u6848\u3002\u90a3\u4e48\u8fd9\u91cc\u5c31\u662f\u5c06 Pod \u7684 Annotations \u5b57\u6bb5\u901a\u8fc7\u4e0a\u9762\u7684\u8def\u5f84\u63d0\u4f9b\u7ed9 init \u5bb9\u5668\uff0cinit \u5bb9\u5668\u6839\u636e\u5176\u4e2d\u7684 template \u83b7\u53d6\u8be5 Pod \u7684\u8f93\u5165\u8f93\u51fa\u3002<\/p>\n<p>\u63a5\u4e0b\u6765\u5224\u65ad\u6839\u636e\u5bb9\u5668\u8fd0\u884c\u65f6\u8fdb\u884c\u5224\u65ad\uff0c\u8fd9\u91cc\u6211\u4eec\u53ea\u8003\u8651 docker \u4f5c\u4e3a\u5bb9\u5668\u8fd0\u884c\u65f6\u7684\u60c5\u51b5\u3002\u6700\u540e\u8c03\u7528<code>NewExecutor<\/code>\u5b9e\u4f8b\u5316\u4e86\u4e00\u4e2a <code>wfExecutor<\/code><\/p>\n<p><strong>StageFiles()<\/strong><\/p>\n<p>\u6e90\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-go line-numbers\">func (we *WorkflowExecutor) StageFiles() error {\n    var filePath string\n    var body []byte\n    switch we.Template.GetType() {\n    case wfv1.TemplateTypeScript:\n        log.Infof(\"Loading script source to %s\", common.ExecutorScriptSourcePath)\n        filePath = common.ExecutorScriptSourcePath\n        body = []byte(we.Template.Script.Source)\n    case wfv1.TemplateTypeResource:\n        log.Infof(\"Loading manifest to %s\", common.ExecutorResourceManifestPath)\n        filePath = common.ExecutorResourceManifestPath\n        body = []byte(we.Template.Resource.Manifest)\n    default:\n        return nil\n    }\n    err := ioutil.WriteFile(filePath, body, 0644)\n    if err != nil {\n        return errors.InternalWrapError(err)\n    }\n    return nil\n}\n<\/code><\/pre>\n<p>\u804c\u8d23\u5f88\u7b80\u5355\uff0c\u6839\u636e template \u7684\u7c7b\u578b\uff0c\u5199\u5165\u5230\u4e0d\u540c\u7684\u6587\u4ef6\u4e2d\uff0c\u6bd4\u5982 script \u5c31\u5199\u5165\u5230 <code>\/argo\/staging\/script<\/code>\u3002\u8fd9\u5c31\u662f\u6211\u4eec\u5728 main \u5bb9\u5668\u4e2d\u6267\u884c\u7684\u811a\u672c\u4e86\u3002<\/p>\n<p><strong>LoadArtifacts<\/strong><\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ LoadArtifacts loads artifacts from location to a container path\nfunc (we *WorkflowExecutor) LoadArtifacts() error {\n    for _, art := range we.Template.Inputs.Artifacts {\n        artDriver, err := we.InitDriver(art)\n\n        var artPath string\n        mnt := common.FindOverlappingVolume(&amp;we.Template, art.Path)\n        if mnt == nil {\n            artPath = path.Join(common.ExecutorArtifactBaseDir, art.Name)\n        } else {\n            \/\/ If we get here, it means the input artifact path overlaps with an user specified\n            \/\/ volumeMount in the container. Because we also implement input artifacts as volume\n            \/\/ mounts, we need to load the artifact into the user specified volume mount,\n            \/\/ as opposed to the `input-artifacts` volume that is an implementation detail\n            \/\/ unbeknownst to the user.\n            log.Infof(\"Specified artifact path %s overlaps with volume mount at %s. Extracting to volume mount\", art.Path, mnt.MountPath)\n            artPath = path.Join(common.ExecutorMainFilesystemDir, art.Path)\n        }\n\n        \/\/ The artifact is downloaded to a temporary location, after which we determine if\n        \/\/ the file is a tarball or not. If it is, it is first extracted then renamed to\n        \/\/ the desired location. If not, it is simply renamed to the location.\n        tempArtPath := artPath + \".tmp\"\n        err = artDriver.Load(&amp;art, tempArtPath)\n        if err != nil {\n            return err\n        }\n        if isTarball(tempArtPath) {\n            err = untar(tempArtPath, artPath)\n            _ = os.Remove(tempArtPath)\n        } else {\n            err = os.Rename(tempArtPath, artPath)\n        }\n\n        if art.Mode != nil {\n            err = os.Chmod(artPath, os.FileMode(*art.Mode))\n        }\n    }\n    return nil\n}\n<\/code><\/pre>\n<p><code>InitDriver<\/code>\u662f\u521d\u59cb\u5316 Artifacts \u7684\u9a71\u52a8\u3002Argo \u652f\u6301\u591a\u79cd\u7c7b\u578b\u7684\u5b58\u50a8\u7cfb\u7edf\uff0c\u5728 v2.3.0 \u8fd9\u4e2a\u7248\u672c\u652f\u6301: s3, http, git, artifactory, hdfs, raw\u3002<\/p>\n<p><code>FindOverlappingVolume<\/code> \u662f\u68c0\u67e5 artifacts \u7684\u8def\u5f84\u548c\u7528\u6237\u6302\u8f7d\u7684\u8def\u5f84\u662f\u5426\u6709\u91cd\u5408\u3002\u5982\u679c\u6709\uff0c\u5219\u8fd4\u56de\u6df1\u5ea6\u6700\u6df1\u7684\u8def\u5f84\uff0c\u5982\u679c\u6ca1\u6709\uff0c\u5219\u8fd4\u56de nil\u3002\u5982\u679c\u8fd4\u56de nil, \u5219\u4f7f\u7528 <code>\/argo\/inputs\/artifacts<\/code> \u4f5c\u4e3a artifacts \u7684\u57fa\u7840\u8def\u5f84\u3002\u5426\u5219\u4f7f\u7528 <code>\/mainctrfs<\/code> \u4f5c\u4e3a\u8def\u5f84\u3002<\/p>\n<p>\u4e0b\u9762\u5c31\u662f\u4e0b\u8f7d\u6587\u4ef6\uff0c\u89e3\u538b\u6587\u4ef6\u5e76\u4fee\u6539\u6743\u9650\u4e86\u3002<\/p>\n<p>\u6ce8\u610f\u5728\u8fd9\u91cc\uff0cinit\u3001wait\u548cmain\u5bb9\u5668\u90fd\u6302\u8f7d\u4e86<code>input-artifacts<\/code>\u548c<code>argo-staging<\/code>\uff0c\u5e76\u4e14 init \u5c06\u8f93\u5165\u548cscript\u653e\u5728\u4e86\u8fd9\u4e24\u4e2a\u5377\u4e2d\uff0c\u6240\u4ee5\u5176\u4ed6\u51e0\u4e2a\u5377\u90fd\u53ef\u4ee5\u5171\u4eab\u8fd9\u4e9b\u6587\u4ef6\u3002<\/p>\n<h2>wait \u5bb9\u5668<\/h2>\n<p>wait\u5bb9\u5668\u7684\u804c\u8d23\u6709\u4ee5\u4e0b\u51e0\u70b9:<\/p>\n<ul>\n<li>\u7b49\u5f85 main \u5bb9\u5668\u7ed3\u675f<\/li>\n<li>\u6740\u6b7b sidecar<\/li>\n<li>\u4fdd\u5b58\u65e5\u5fd7<\/li>\n<li>\u4fdd\u5b58 parameters<\/li>\n<li>\u4fdd\u5b58 artifacts<\/li>\n<li>\u83b7\u53d6\u811a\u672c\u7684\u8f93\u51fa\u6d41<\/li>\n<li>\u5c06\u8f93\u51fa\u653e\u5728 Annotations \u4e0a<\/li>\n<\/ul>\n<p>\u4e0b\u9762\u6211\u4eec\u770b\u8fd9\u4e9b\u529f\u80fd\u70b9\u7684\u5b9e\u73b0\uff1a<\/p>\n<p><strong>\u7b49\u5f85 main \u5bb9\u5668\u7ed3\u675f<\/strong><\/p>\n<pre><code class=\"line-numbers\">\/\/ Wait is the sidecar container logic which waits for the main container to complete.\n\/\/ Also monitors for updates in the pod annotations which may change (e.g. terminate)\n\/\/ Upon completion, kills any sidecars after it finishes.\nfunc (we *WorkflowExecutor) Wait() error {\n    \/\/ WaitInit() \u662f\u521d\u59cb\u5316\u64cd\u4f5c\uff0c\u53ea\u6709 PSN \u9700\u8981\n    err := we.RuntimeExecutor.WaitInit()\n    if err != nil {\n        return err\n    }\n    log.Infof(\"Waiting on main container\")\n    \/\/ waitMainContainerStart\u7684\u4e3b\u8981\u539f\u7406\u662f\u5468\u671f\u8f6e\u8be2Pod\u4e2d\u7684\u6240\u6709\u5bb9\u5668\uff0c\u68c0\u67e5main\u5bb9\u5668\u7684ContainerID\u5b57\u6bb5\n    \/\/ \u4e0d\u4e3a\u7a7a\u8bf4\u660e\u542f\u52a8\u4e86\n    mainContainerID, err := we.waitMainContainerStart()\n    if err != nil {\n        return err\n    }\n    log.Infof(\"main container started with container ID: %s\", mainContainerID)\n    ctx, cancel := context.WithCancel(context.Background())\n    defer cancel()\n\n    \/\/ monitorAnnotations\u662f\u56e0\u4e3apod\u7684annotations\u4f1a\u66f4\u6539\n    annotationUpdatesCh := we.monitorAnnotations(ctx)\n    \/\/ \u8d85\u65f6\u4f1a\u6740\u6b7b\n    go we.monitorDeadline(ctx, annotationUpdatesCh)\n\n    \/\/ \u8fd9\u91cc\u662f\u76f4\u63a5\u7528ContainerRuntime\u53bb\u7b49\u5f85\u5bb9\u5668\u7ed3\u675f\u7684\uff0c\u6bd4\u5982docker,\u76f4\u63a5\u8c03\u7528docker wait\n    err = we.RuntimeExecutor.Wait(mainContainerID)\n    if err != nil {\n        return err\n    }\n    log.Infof(\"Main container completed\")\n    return nil\n}\n<\/code><\/pre>\n<p><strong>\u6740\u6b7b sidecar<\/strong><\/p>\n<p>main \u5bb9\u5668\u8fd0\u884c\u7ed3\u675f\u540e\uff0cwait \u5bb9\u5668\u4f1a\u8d1f\u8d23\u6740\u6b7b\u5176\u4ed6\u5bb9\u5668\uff08\u8fd9\u4e2a\u8ba9\u6211\u53d1\u73b0\u4e86\u4e4b\u524d\u7528 sidecar \u505a main \u5bb9\u5668\u8fd0\u884c\u7ed3\u675f\u540e\u7684\u6e05\u7406\u5de5\u4f5c\u4e00\u76f4\u65e0\u6548\u7684\u539f\u56e0)\u3002<\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ KillSidecars kills any sidecars to the main container\nfunc (we *WorkflowExecutor) KillSidecars() error {\n    if len(we.Template.Sidecars) == 0 {\n        log.Infof(\"No sidecars\")\n        return nil\n    }\n    log.Infof(\"Killing sidecars\")\n    pod, err := we.getPod()\n    if err != nil {\n        return err\n    }\n    sidecarIDs := make([]string, 0)\n    \/\/ \u904d\u5386pod\u4e2d\u7684\u5bb9\u5668\uff0c\u6392\u9664main\u548cwait,\u7136\u540e\u8c03\u7528runtime\u6765\u6740\u6b7b\u5bb9\u5668\n    for _, ctrStatus := range pod.Status.ContainerStatuses {\n        if ctrStatus.Name == common.MainContainerName || ctrStatus.Name == common.WaitContainerName {\n            continue\n        }\n        if ctrStatus.State.Terminated != nil {\n            continue\n        }\n        containerID := containerID(ctrStatus.ContainerID)\n        log.Infof(\"Killing sidecar %s (%s)\", ctrStatus.Name, containerID)\n        sidecarIDs = append(sidecarIDs, containerID)\n    }\n    if len(sidecarIDs) == 0 {\n        return nil\n    }\n    return we.RuntimeExecutor.Kill(sidecarIDs)\n}\n<\/code><\/pre>\n<p><strong>\u4fdd\u5b58\u65e5\u5fd7<\/strong><\/p>\n<p>argo \u662f\u652f\u6301\u5c06 main \u5bb9\u5668\u4e2d\u7684\u65e5\u5fd7\u6301\u4e45\u5316\u5e76\u4fdd\u5b58\u5230\u6307\u5b9a\u7684\u5730\u65b9\u7684(s3, hdfs, Artifactory)\u3002\u8fd9\u5728 argo \u7684\u6587\u6863\u4e0a\u597d\u50cf\u6ca1\u6709\u63d0\u5230\u8fc7\u3002\u8fd9\u4e00\u90e8\u5206\u7684\u903b\u8f91\u6bd4\u8f83\u7b80\u5355\uff0c\u5c31\u662f\u901a\u8fc7 ContainerRuntime \u83b7\u53d6\u83b7\u53d6\u5bb9\u5668\u4e2d\u7684\u8f93\u51fa\u6d41\uff0c\u7136\u540e\u5b58\u6210\u6587\u4ef6\uff0c\u901a\u8fc7 argo \u4e2d\u7684 storage driver \u4fdd\u5b58\u4e0b\u6765\u3002<\/p>\n<p><strong>\u4fdd\u5b58 parameters<\/strong><\/p>\n<pre><code class=\"language-go line-numbers\">\/\/ SaveParameters will save the content in the specified file path as output parameter value\nfunc (we *WorkflowExecutor) SaveParameters() error {\n    if len(we.Template.Outputs.Parameters) == 0 {\n        log.Infof(\"No output parameters\")\n        return nil\n    }\n    log.Infof(\"Saving output parameters\")\n    mainCtrID, err := we.GetMainContainerID()\n    if err != nil {\n        return err\n    }\n\n    \/\/ \u904d\u5386\u6a21\u677f\u53c2\u6570\n    for i, param := range we.Template.Outputs.Parameters {\n        log.Infof(\"Saving path output parameter: %s\", param.Name)\n        \/\/ Determine the file path of where to find the parameter\n        if param.ValueFrom == nil || param.ValueFrom.Path == \"\" {\n            continue\n        }\n\n        var output string\n        if we.isBaseImagePath(param.ValueFrom.Path) {\n            log.Infof(\"Copying %s from base image layer\", param.ValueFrom.Path)\n            \/\/ \u5bb9\u5668\u5185\uff0c\u901a\u8fc7 runtime \u83b7\u53d6\n            output, err = we.RuntimeExecutor.GetFileContents(mainCtrID, param.ValueFrom.Path)\n            if err != nil {\n                return err\n            }\n        } else {\n            log.Infof(\"Copying %s from from volume mount\", param.ValueFrom.Path)\n            mountedPath := filepath.Join(common.ExecutorMainFilesystemDir, param.ValueFrom.Path)\n            \/\/ \u5bb9\u5668\u7684\u6302\u8f7d\u5377\uff0c\u76f4\u63a5\u83b7\u53d6\n            out, err := ioutil.ReadFile(mountedPath)\n            if err != nil {\n                return err\n            }\n            output = string(out)\n        }\n\n        outputLen := len(output)\n        \/\/ Trims off a single newline for user convenience\n        if outputLen &gt; 0 &amp;&amp; output[outputLen-1] == '\\n' {\n            output = output[0 : outputLen-1]\n        }\n        \/\/ \u4fdd\u5b58\u4e0b\u6765\n        we.Template.Outputs.Parameters[i].Value = &amp;output\n        log.Infof(\"Successfully saved output parameter: %s\", param.Name)\n    }\n    return nil\n}\n<\/code><\/pre>\n<p><strong>\u4fdd\u5b58 artifacts<\/strong><\/p>\n<p>\u4fdd\u5b58 artifacts \u548c \u4fdd\u5b58 parameters \u7684\u64cd\u4f5c\u662f\u4e00\u6837\u7684\u3002<\/p>\n<pre><code class=\"line-numbers\">\/\/ SaveArtifacts uploads artifacts to the archive location\nfunc (we *WorkflowExecutor) SaveArtifacts() error {\n    if len(we.Template.Outputs.Artifacts) == 0 {\n        log.Infof(\"No output artifacts\")\n        return nil\n    }\n    log.Infof(\"Saving output artifacts\")\n    mainCtrID, err := we.GetMainContainerID()\n    if err != nil {\n        return err\n    }\n\n    err = os.MkdirAll(tempOutArtDir, os.ModePerm)\n    if err != nil {\n        return errors.InternalWrapError(err)\n    }\n\n    for i, art := range we.Template.Outputs.Artifacts {\n        err := we.saveArtifact(mainCtrID, &amp;art)\n        if err != nil {\n            return err\n        }\n        we.Template.Outputs.Artifacts[i] = art\n    }\n    return nil\n}\n<\/code><\/pre>\n<p><strong>\u83b7\u53d6\u811a\u672c\u7684\u8f93\u51fa\u6d41<\/strong><\/p>\n<p>\u76f4\u63a5\u8c03\u7528 runtime \u53bb\u83b7\u53d6 main \u5bb9\u5668\u7684\u8f93\u51fa\u6d41\uff0c\u7136\u540e\u4fdd\u5b58\u5230 template.outputs \u4e2d<\/p>\n<pre><code class=\"language-go line-numbers\">func (we *WorkflowExecutor) CaptureScriptResult() error {\n    if we.Template.Script == nil {\n        return nil\n    }\n    log.Infof(\"Capturing script output\")\n    mainContainerID, err := we.GetMainContainerID()\n    if err != nil {\n        return err\n    }\n    reader, err := we.RuntimeExecutor.GetOutputStream(mainContainerID, false)\n    if err != nil {\n        return err\n    }\n    defer func() { _ = reader.Close() }()\n    bytes, err := ioutil.ReadAll(reader)\n    if err != nil {\n        return errors.InternalWrapError(err)\n    }\n    out := string(bytes)\n    \/\/ Trims off a single newline for user convenience\n    outputLen := len(out)\n    if outputLen &gt; 0 &amp;&amp; out[outputLen-1] == '\\n' {\n        out = out[0 : outputLen-1]\n    }\n    we.Template.Outputs.Result = &amp;out\n    return nil\n}\n<\/code><\/pre>\n<p><strong>\u5c06\u8f93\u51fa\u653e\u5728 Annotations \u4e0a<\/strong><\/p>\n<p>\u5c06 outputs \u5b58\u5728 pod \u7684 annotations \u4e0a\u3002<\/p>\n<pre><code class=\"language-go line-numbers\">func (we *WorkflowExecutor) AnnotateOutputs(logArt *wfv1.Artifact) error {\n    outputs := we.Template.Outputs.DeepCopy()\n    if logArt != nil {\n        outputs.Artifacts = append(outputs.Artifacts, *logArt)\n    }\n\n    if !outputs.HasOutputs() {\n        return nil\n    }\n    log.Infof(\"Annotating pod with output\")\n    outputBytes, err := json.Marshal(outputs)\n    if err != nil {\n        return errors.InternalWrapError(err)\n    }\n    return we.AddAnnotation(common.AnnotationKeyOutputs, string(outputBytes))\n}\n<\/code><\/pre>\n<h2>\u603b\u7ed3<\/h2>\n<p>init \u5bb9\u5668\u505a\u4e86 pod \u7684\u521d\u59cb\u5316\uff0c\u5305\u62ec\u5b58\u50a8 script\uff0c\u4e0b\u8f7d artifacts\u7b49\u7b49\uff0c\u8fd9\u6837\u6211\u4eec\u7684 main \u5bb9\u5668\u5c31\u4e0d\u7528\u5173\u5fc3\u8f93\u5165\u7684\u6765\u6e90\uff0c\u53ea\u9700\u8981\u5728\u6307\u5b9a\u5730\u65b9\u4f7f\u7528\u5373\u53ef\u3002wait \u5bb9\u5668\u8d1f\u8d23\u76d1\u63a7 main \u5bb9\u5668\u7684\u751f\u547d\u5468\u671f\uff0c\u5728 main \u5bb9\u5668\u4e2d\u7684\u4e3b\u8981\u903b\u8f91\u8fd0\u884c\u7ed3\u675f\u4e4b\u540e\uff0c\u8d1f\u8d23\u5c06\u8f93\u51fa\u90e8\u5206\u8bfb\u53d6\uff0c\u6301\u4e45\u5316\uff0c\u8fd9\u6837 main \u5bb9\u5668\u5c31\u4e0d\u7528\u64cd\u5fc3\u5982\u4f55\u5c06\u8be5\u6b65\u4ea7\u751f\u7684\u7ed3\u679c\u4f20\u5230\u540e\u9762\u7684\u6b65\u9aa4\u4e0a\u7684\u95ee\u9898\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7b80\u4ecb argo\u662f\u4e00\u4e2a\u5de5\u4f5c\u6d41\u7684\u8c03\u5ea6\u5f15\u64ce\uff0c\u652f\u6301 Steps \u548c DAG \u8fd9\u4e24\u79cd\u5de5\u4f5c\u6d41\u3002 Steps: \u662f\u6309\u7167\u6b65\u9aa4\uff0c &hellip; <a href=\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\" class=\"more-link\">\u7ee7\u7eed\u9605\u8bfb<span class=\"screen-reader-text\">argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":529,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89],"tags":[102,104,103],"class_list":["post-528","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-k8s","tag-argo","tag-k8s","tag-workflow"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b\" \/>\n<meta property=\"og:description\" content=\"\u7b80\u4ecb argo\u662f\u4e00\u4e2a\u5de5\u4f5c\u6d41\u7684\u8c03\u5ea6\u5f15\u64ce\uff0c\u652f\u6301 Steps \u548c DAG \u8fd9\u4e24\u79cd\u5de5\u4f5c\u6d41\u3002 Steps: \u662f\u6309\u7167\u6b65\u9aa4\uff0c &hellip; \u7ee7\u7eed\u9605\u8bfbargo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\" \/>\n<meta property=\"og:site_name\" content=\"\u4e00\u53ea\u5b89\u9759\u7684\u732b\" \/>\n<meta property=\"article:published_time\" content=\"2020-01-10T13:52:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-05T13:35:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png\" \/>\n\t<meta property=\"og:image:width\" content=\"458\" \/>\n\t<meta property=\"og:image:height\" content=\"225\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"jiangpengfei\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"jiangpengfei\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\"},\"author\":{\"name\":\"jiangpengfei\",\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685\"},\"headline\":\"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790\",\"datePublished\":\"2020-01-10T13:52:39+00:00\",\"dateModified\":\"2023-07-05T13:35:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\"},\"wordCount\":110,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685\"},\"image\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png\",\"keywords\":[\"argo\",\"k8s\",\"workflow\"],\"articleSection\":[\"k8s\"],\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\",\"url\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\",\"name\":\"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b\",\"isPartOf\":{\"@id\":\"https:\/\/www.myway5.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png\",\"datePublished\":\"2020-01-10T13:52:39+00:00\",\"dateModified\":\"2023-07-05T13:35:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage\",\"url\":\"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png\",\"contentUrl\":\"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png\",\"width\":458,\"height\":225},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.myway5.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.myway5.com\/#website\",\"url\":\"https:\/\/www.myway5.com\/\",\"name\":\"\u4e00\u53ea\u5b89\u9759\u7684\u732b\",\"description\":\"\u60f3\u5565\u5462\",\"publisher\":{\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.myway5.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-Hans\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685\",\"name\":\"jiangpengfei\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f8c7de757f6e0247412bcfd31b7c2271?s=96&d=monsterid&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f8c7de757f6e0247412bcfd31b7c2271?s=96&d=monsterid&r=g\",\"caption\":\"jiangpengfei\"},\"logo\":{\"@id\":\"https:\/\/www.myway5.com\/#\/schema\/person\/image\/\"},\"url\":\"https:\/\/www.myway5.com\/index.php\/author\/joyme\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/","og_locale":"zh_CN","og_type":"article","og_title":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b","og_description":"\u7b80\u4ecb argo\u662f\u4e00\u4e2a\u5de5\u4f5c\u6d41\u7684\u8c03\u5ea6\u5f15\u64ce\uff0c\u652f\u6301 Steps \u548c DAG \u8fd9\u4e24\u79cd\u5de5\u4f5c\u6d41\u3002 Steps: \u662f\u6309\u7167\u6b65\u9aa4\uff0c &hellip; \u7ee7\u7eed\u9605\u8bfbargo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790","og_url":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/","og_site_name":"\u4e00\u53ea\u5b89\u9759\u7684\u732b","article_published_time":"2020-01-10T13:52:39+00:00","article_modified_time":"2023-07-05T13:35:48+00:00","og_image":[{"width":458,"height":225,"url":"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png","type":"image\/png"}],"author":"jiangpengfei","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"jiangpengfei","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"8 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#article","isPartOf":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/"},"author":{"name":"jiangpengfei","@id":"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685"},"headline":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790","datePublished":"2020-01-10T13:52:39+00:00","dateModified":"2023-07-05T13:35:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/"},"wordCount":110,"commentCount":0,"publisher":{"@id":"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685"},"image":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage"},"thumbnailUrl":"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png","keywords":["argo","k8s","workflow"],"articleSection":["k8s"],"inLanguage":"zh-Hans","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/","url":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/","name":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790 - \u4e00\u53ea\u5b89\u9759\u7684\u732b","isPartOf":{"@id":"https:\/\/www.myway5.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage"},"image":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage"},"thumbnailUrl":"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png","datePublished":"2020-01-10T13:52:39+00:00","dateModified":"2023-07-05T13:35:48+00:00","breadcrumb":{"@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/"]}]},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#primaryimage","url":"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png","contentUrl":"https:\/\/www.myway5.com\/wp-content\/uploads\/2020\/01\/argo-a099ca3512e83579d67b0aa9ede5261a-1df76.png","width":458,"height":225},{"@type":"BreadcrumbList","@id":"https:\/\/www.myway5.com\/index.php\/2020\/01\/10\/argo-input-output\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.myway5.com\/"},{"@type":"ListItem","position":2,"name":"argo\u7684\u8f93\u5165\u8f93\u51fa\u6e90\u4ee3\u7801\u5206\u6790"}]},{"@type":"WebSite","@id":"https:\/\/www.myway5.com\/#website","url":"https:\/\/www.myway5.com\/","name":"\u4e00\u53ea\u5b89\u9759\u7684\u732b","description":"\u60f3\u5565\u5462","publisher":{"@id":"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.myway5.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-Hans"},{"@type":["Person","Organization"],"@id":"https:\/\/www.myway5.com\/#\/schema\/person\/b19267e8b106343431e163ec96950685","name":"jiangpengfei","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.myway5.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f8c7de757f6e0247412bcfd31b7c2271?s=96&d=monsterid&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f8c7de757f6e0247412bcfd31b7c2271?s=96&d=monsterid&r=g","caption":"jiangpengfei"},"logo":{"@id":"https:\/\/www.myway5.com\/#\/schema\/person\/image\/"},"url":"https:\/\/www.myway5.com\/index.php\/author\/joyme\/"}]}},"views":6389,"_links":{"self":[{"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/posts\/528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/comments?post=528"}],"version-history":[{"count":1,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/posts\/528\/revisions"}],"predecessor-version":[{"id":1561,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/posts\/528\/revisions\/1561"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/media\/529"}],"wp:attachment":[{"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/media?parent=528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/categories?post=528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.myway5.com\/index.php\/wp-json\/wp\/v2\/tags?post=528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}