mozillazg's Bloghttps://mozillazg.com/2024-03-10T00:00:00+00:00如何在本地 checkout GitHub 上外部贡献者提交的 PR 所在 fork 仓库的分支代码2024-03-10T00:00:00+00:002024-03-10T00:00:00+00:00mozillazgtag:mozillazg.com,2024-03-10:2024/03/git-checkout-github-pr-codes-to-local.html<p>在日常处理 GitHub 上外部贡献者提交的 PR 时,可能会想将 PR 对应的代码 checkout 到本地,
这里涉及到如何快速 checkout PR 所在 fork 仓库的分支代码。</p>
<p>通常我们可能会通过 git clone 对应的 fork 仓库来实现,但是其实还有一个更便捷、不需要切换目录进行 clone 的方法。</p>
<p>我们可以通过下面的方法实现快速 checkout PR 对应的 fork 仓库分支代码的需求:</p>
<pre class="literal-block">
git fetch origin pull/<ID>/head:<BRANCHNAME>
git checkout <BRANCHNAME>
</pre>
<p>实际使用时,需要将上面命令中的 <tt class="docutils literal"><ID></tt> 替换为对应的 PR ID,需要将 <tt class="docutils literal"><BRANCHNAME></tt> 替换为你想在本地新建的分支名称。
下面是一个实际使用的示例(将 ID 为 47 的 PR 代码 checkout 到本地的 pr47 分支中):</p>
<pre class="literal-block">
$ git fetch origin pull/47/head:pr47
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 10 (delta 4), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (10/10), 3.25 MiB | 862.00 KiB/s, done.
From github.com:mozillazg/XXXX
* [new ref] refs/pull/47/head -> pr47
$ git log pr47
$ git checkout pr47
Switched to branch 'pr47'
</pre>
Amazon EKS Pod Identity 新特性探索2023-12-03T00:00:00+00:002023-12-03T00:00:00+00:00mozillazgtag:mozillazg.com,2023-12-03:2023/12/security-deep-dive-into-aws-eks-pod-identity-feature.html<p>本文将简单探索一下 AWS 本周新发布的名为 <a class="reference external" href="https://aws.amazon.com/blogs/aws/amazon-eks-pod-identity-simplifies-iam-permissions-for-applications-on-amazon-eks-clusters/">Amazon EKS Pod Identity</a> 的 EKS 安全特性。</p>
<div class="section" id="section-1">
<h2 id="hidsection-1">功能介绍<a class="headerlink" href="#hidsection-1" title="Permalink to this headline">¶</a></h2>
<p>Amazon EKS Pod Identity 是 AWS 对 EKS 原有的 <a class="reference external" href="https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/">IAM roles for service accounts (IRSA)</a> 功能的补充,通过新增的 EKS Pod Identity 功能,用户可以用更简便的方式实现为 Pod 安全的授予 AWS API 访问权限,
并且所有的配置管理操作都可以通过 AWS API 或者控制台完成。</p>
</div>
<div class="section" id="section-2">
<h2 id="hidsection-2">使用方法<a class="headerlink" href="#hidsection-2" title="Permalink to this headline">¶</a></h2>
<p>用户只需执行如下操作, 即可基于 EKS Pod Identity 特性实现为 Pod 内应用安全的授予 AWS API 访问权限。</p>
<ol class="arabic simple">
<li>首先,需要创建一个 IAM 角色,确保该角色信任 <tt class="docutils literal">pods.eks.amazonaws.com</tt> 。角色信任策略示例如下。</li>
</ol>
<div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Principal"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Service"</span><span class="p">:</span><span class="w"> </span><span class="s2">"pods.eks.amazonaws.com"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"sts:AssumeRole"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"sts:TagSession"</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>
<ol class="arabic simple" start="2">
<li>其次,需要在 EKS 集群内安装 <a class="reference external" href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html">eks-pod-identity-agent</a>
组件(支持通过控制台安装)。</li>
</ol>
<div class="highlight"><pre><span></span>aws<span class="w"> </span>eks<span class="w"> </span>create-addon<span class="w"> </span><span class="se">\</span>
--cluster-name<span class="w"> </span><CLUSTER_NAME><span class="w"> </span><span class="se">\</span>
--addon-name<span class="w"> </span>eks-pod-identity-agent<span class="w"> </span><span class="se">\</span>
--addon-version<span class="w"> </span>v1.0.0-eksbuild.1
</pre></div>
<ol class="arabic simple" start="3">
<li>然后,需要配置应用 Pod 所使用的 Service Account 与 AWS IAM 角色之间的关联关系,
允许使用该 Service Account 的应用扮演特定的 IAM 角色(支持通过控制台配置)。</li>
</ol>
<div class="highlight"><pre><span></span>aws<span class="w"> </span>eks<span class="w"> </span>create-pod-identity-association<span class="w"> </span><span class="se">\</span>
<span class="w"> </span>--cluster-name<span class="w"> </span><CLUSTER_NAME><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>--namespace<span class="w"> </span><NAMESPACE><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>--service-account<span class="w"> </span><SERVICE_ACCOUNT_NAME><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>--role-arn<span class="w"> </span><IAM_ROLE_ARN>
</pre></div>
<ol class="arabic simple" start="4">
<li>最后,应用程序需要更新使用最新的支持 EKS Pod Identity 特性的 <a class="reference external" href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk.html">AWS SDK</a> ,
并且代码里需要使用 SDK 提供的 <a class="reference external" href="https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html#credentialProviderChain">默认凭证搜索逻辑</a>
或者显式调用 EKS Pod Identity 依赖的 <a class="reference external" href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html">Container credential provider</a> 。</li>
</ol>
</div>
<div class="section" id="section-3">
<h2 id="hidsection-3">工作流程<a class="headerlink" href="#hidsection-3" title="Permalink to this headline">¶</a></h2>
<p>EKS Pod Identity 特性的工作流程如下。</p>
<p><img alt="image" src="/static/images/security/eks-pod-identity.png" /></p>
<ol class="arabic simple">
<li>当用户/Controller 向 apiserver 提交 Pod 时,会触发 <a class="reference external" href="https://github.com/aws/amazon-eks-pod-identity-webhook">eks-pod-identity-webhook</a> 的 mutating webhook 流程。</li>
<li>eks-pod-identity-webhook 的 mutating webhook 流程会为 Pod 挂载 service account oidc token 文件以及配置环境变量
(<tt class="docutils literal">AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE</tt>, <tt class="docutils literal">AWS_CONTAINER_CREDENTIALS_FULL_URI</tt> )。</li>
</ol>
<div class="highlight"><pre><span></span><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w"> </span><span class="w w-Error"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_STS_REGIONAL_ENDPOINTS</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">regional</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_DEFAULT_REGION</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">us-west-2</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_REGION</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">us-west-2</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_CONTAINER_CREDENTIALS_FULL_URI</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">http://169.254.170.23/v1/credentials</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token</span>
<span class="w"> </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/var/run/secrets/pods.eks.amazonaws.com/serviceaccount</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-token</span>
<span class="w"> </span><span class="nt">readOnly</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="nt">volumes</span><span class="p">:</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-token</span>
<span class="w"> </span><span class="nt">projected</span><span class="p">:</span>
<span class="w"> </span><span class="nt">defaultMode</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">420</span>
<span class="w"> </span><span class="nt">sources</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">serviceAccountToken</span><span class="p">:</span>
<span class="w"> </span><span class="nt">audience</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pods.eks.amazonaws.com</span>
<span class="w"> </span><span class="nt">expirationSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">86400</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-token</span>
</pre></div>
<ol class="arabic simple" start="3">
<li>Pod 容器内的应用使用的 AWS SDK 将使用通过环境变量 <tt class="docutils literal">AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE</tt> 获取的
service account oidc token 访问环境变量 <tt class="docutils literal">AWS_CONTAINER_CREDENTIALS_FULL_URI</tt> 指向的地址
(<tt class="docutils literal"><span class="pre">http://169.254.170.23/v1/credentials</span></tt>)获取 AWS sts token。</li>
</ol>
<div class="highlight"><pre><span></span><span class="l l-Scalar l-Scalar-Plain">$ curl $AWS_CONTAINER_CREDENTIALS_FULL_URI -H "Authorization</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$(cat $AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE)" 2>/dev/null |jq</span>
<span class="p p-Indicator">{</span>
<span class="w"> </span><span class="s">"AccessKeyId"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"ASXXXXXXXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"SecretAccessKey"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"+j5XXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"Token"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"IQoJb3JpXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"AccountId"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"5XXXXXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"Expiration"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"2023-12-03T13:13:26Z"</span>
<span class="p p-Indicator">}</span>
</pre></div>
<ol class="arabic simple" start="4">
<li><tt class="docutils literal">AWS_CONTAINER_CREDENTIALS_FULL_URI</tt> 指向的其实是 Pod 所在节点上部署的 eks-pod-identity-agent 组件 Pod 所暴露的服务。
eks-pod-identity-agent 收到请求后,将使用传递过来的 oidc token 访问 EKS 新增的 <a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_auth_AssumeRoleForPodIdentity.html">AssumeRoleForPodIdentity</a> API 获取所需的 AWS sts token,然后将获取到的 sts token 返回给客户端。</li>
</ol>
<div class="highlight"><pre><span></span><span class="l l-Scalar l-Scalar-Plain">$ aws eks-auth assume-role-for-pod-identity --cluster-name test --token $(cat $AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE) |jq</span>
<span class="l l-Scalar l-Scalar-Plain">{</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">"subject"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="p p-Indicator">{</span>
<span class="w"> </span><span class="s">"namespace"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"default"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"serviceAccount"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"default"</span>
<span class="w"> </span><span class="p p-Indicator">}</span><span class="err">,</span>
<span class="w"> </span><span class="s">"audience"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"pods.eks.amazonaws.com"</span><span class="err">,</span>
<span class="w"> </span><span class="s">"podIdentityAssociation"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="p p-Indicator">{</span>
<span class="w"> </span><span class="s">"associationArn"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"arn:aws:eks:us-west-2:5XXXXXXXXXXX:podidentityassociation/test/a-6aaXXXXXXXXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"associationId"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"a-6aaXXXXXXXXXXXXXX"</span>
<span class="w"> </span><span class="p p-Indicator">}</span><span class="err">,</span>
<span class="w"> </span><span class="s">"assumedRoleUser"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="p p-Indicator">{</span>
<span class="w"> </span><span class="s">"arn"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"arn:aws:sts::5XXXXXXXXXXX:assumed-role/test-eks-pod-identity/eks-test-XXXXXXXXXXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"assumeRoleId"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"ARXXXXXXXXXXXXXXXXXXX:eks-test-XXXXXXXXXXXXXXXXXX"</span>
<span class="w"> </span><span class="p p-Indicator">}</span><span class="err">,</span>
<span class="w"> </span><span class="s">"credentials"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="p p-Indicator">{</span>
<span class="w"> </span><span class="s">"sessionToken"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"IQoXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"secretAccessKey"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"nR4XXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"accessKeyId"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"ASXXXXXXXXXXXXXXXXXX"</span><span class="p p-Indicator">,</span>
<span class="w"> </span><span class="s">"expiration"</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="s">"2023-12-03T13:37:22+00:00"</span>
<span class="w"> </span><span class="p p-Indicator">}</span>
<span class="err">}</span>
</pre></div>
<ol class="arabic simple" start="5">
<li>应用调用的 AWS SDK 使用获取到的 sts token 访问应用所需的 AWS 云产品 API。</li>
</ol>
<p>这个流程中有几个关键的组件和信息需要重点关注,下面将逐个说明。</p>
</div>
<div class="section" id="eks-pod-identity-webhook">
<h2 id="hideks-pod-identity-webhook">eks-pod-identity-webhook<a class="headerlink" href="#hideks-pod-identity-webhook" title="Permalink to this headline">¶</a></h2>
<p>EKS Pod Identity 功能直接复用 IRSA 功能所依赖的 <a class="reference external" href="https://github.com/aws/amazon-eks-pod-identity-webhook">eks-pod-identity-webhook</a> 组件,
使用这个组件实现为 Pod 自动注入所需的 oidc token 配置以及环境变量配置。并且,
EKS 集群控制面中部署的 eks-pod-identity-webhook 为 EKS Pod Identity 做了特殊优化,
只有当对应的 service account 未包含 IRSA 相关配置,并且存在与之关联
的 IAM 角色信息(通过前面的使用方法中介绍的方法关联角色)时,才会为 Pod 注入 EKS Pod Identity 相关配置。</p>
<p>eks-pod-identity-webhook 为了支持 EKS Pod Identity 所作的修改可以参考开源实现(开源实现缺少判断存在关联角色的逻辑)
对应的 PR <a class="reference external" href="https://github.com/aws/amazon-eks-pod-identity-webhook/pull/189">#189</a> 以及
<a class="reference external" href="https://github.com/aws/amazon-eks-pod-identity-webhook/pull/196">#196</a> 。</p>
</div>
<div class="section" id="eks-pod-identity-agent">
<h2 id="hideks-pod-identity-agent">eks-pod-identity-agent<a class="headerlink" href="#hideks-pod-identity-agent" title="Permalink to this headline">¶</a></h2>
<p>官方推荐的 EKS Pod Identity 实现方案依赖在集群里安装名为 <a class="reference external" href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html">eks-pod-identity-agent</a>
的组件。该组件的工作负载 YAML 如下。</p>
<div class="highlight"><pre><span></span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">apps/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DaemonSet</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">annotations</span><span class="p">:</span>
<span class="w"> </span><span class="nt">deprecated.daemonset.template.generation</span><span class="p">:</span><span class="w"> </span><span class="s">"1"</span>
<span class="w"> </span><span class="nt">creationTimestamp</span><span class="p">:</span><span class="w"> </span><span class="s">"2023-12-03T04:24:15Z"</span>
<span class="w"> </span><span class="nt">generation</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/instance</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/managed-by</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Helm</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.0.25</span>
<span class="w"> </span><span class="nt">helm.sh/chart</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent-1.0.0</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">kube-system</span>
<span class="w"> </span><span class="nt">resourceVersion</span><span class="p">:</span><span class="w"> </span><span class="s">"8978"</span>
<span class="w"> </span><span class="nt">uid</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">08c03e91-69d4-460b-8acb-b9f9f546dd87</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">revisionHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">matchLabels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/instance</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">template</span><span class="p">:</span>
<span class="w"> </span><span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">creationTimestamp</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">null</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/instance</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">affinity</span><span class="p">:</span>
<span class="w"> </span><span class="nt">nodeAffinity</span><span class="p">:</span>
<span class="w"> </span><span class="nt">requiredDuringSchedulingIgnoredDuringExecution</span><span class="p">:</span>
<span class="w"> </span><span class="nt">nodeSelectorTerms</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">matchExpressions</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">kubernetes.io/os</span>
<span class="w"> </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">In</span>
<span class="w"> </span><span class="nt">values</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">linux</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">kubernetes.io/arch</span>
<span class="w"> </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">In</span>
<span class="w"> </span><span class="nt">values</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">amd64</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">arm64</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks.amazonaws.com/compute-type</span>
<span class="w"> </span><span class="nt">operator</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">NotIn</span>
<span class="w"> </span><span class="nt">values</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">fargate</span>
<span class="w"> </span><span class="nt">containers</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">args</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">--port</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"80"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">--cluster-name</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">--probe-port</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"2703"</span>
<span class="w"> </span><span class="nt">command</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/go-runner</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/eks-pod-identity-agent</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">server</span>
<span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">AWS_REGION</span>
<span class="w"> </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">us-west-2</span>
<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/eks-pod-identity-agent:0.0.25</span>
<span class="w"> </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Always</span>
<span class="w"> </span><span class="nt">livenessProbe</span><span class="p">:</span>
<span class="w"> </span><span class="nt">failureThreshold</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w"> </span><span class="nt">httpGet</span><span class="p">:</span>
<span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">localhost</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/healthz</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">probes-port</span>
<span class="w"> </span><span class="nt">scheme</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HTTP</span>
<span class="w"> </span><span class="nt">initialDelaySeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">30</span>
<span class="w"> </span><span class="nt">periodSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10</span>
<span class="w"> </span><span class="nt">successThreshold</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">timeoutSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent</span>
<span class="w"> </span><span class="nt">ports</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">80</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">proxy</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">containerPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2703</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">probes-port</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="nt">readinessProbe</span><span class="p">:</span>
<span class="w"> </span><span class="nt">failureThreshold</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">30</span>
<span class="w"> </span><span class="nt">httpGet</span><span class="p">:</span>
<span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">localhost</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/readyz</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">probes-port</span>
<span class="w"> </span><span class="nt">scheme</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HTTP</span>
<span class="w"> </span><span class="nt">initialDelaySeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">periodSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10</span>
<span class="w"> </span><span class="nt">successThreshold</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">timeoutSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10</span>
<span class="w"> </span><span class="nt">resources</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{}</span>
<span class="w"> </span><span class="nt">securityContext</span><span class="p">:</span>
<span class="w"> </span><span class="nt">capabilities</span><span class="p">:</span>
<span class="w"> </span><span class="nt">add</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">CAP_NET_BIND_SERVICE</span>
<span class="w"> </span><span class="nt">terminationMessagePath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/dev/termination-log</span>
<span class="w"> </span><span class="nt">terminationMessagePolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">File</span>
<span class="w"> </span><span class="nt">dnsPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ClusterFirst</span>
<span class="w"> </span><span class="nt">hostNetwork</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">initContainers</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">command</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/go-runner</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/eks-pod-identity-agent</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">initialize</span>
<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/eks-pod-identity-agent:0.0.25</span>
<span class="w"> </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Always</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">eks-pod-identity-agent-init</span>
<span class="w"> </span><span class="nt">resources</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{}</span>
<span class="w"> </span><span class="nt">securityContext</span><span class="p">:</span>
<span class="w"> </span><span class="nt">privileged</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">terminationMessagePath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/dev/termination-log</span>
<span class="w"> </span><span class="nt">terminationMessagePolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">File</span>
<span class="w"> </span><span class="nt">priorityClassName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">system-node-critical</span>
<span class="w"> </span><span class="nt">restartPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Always</span>
<span class="w"> </span><span class="nt">schedulerName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">default-scheduler</span>
<span class="w"> </span><span class="nt">securityContext</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{}</span>
<span class="w"> </span><span class="nt">terminationGracePeriodSeconds</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">30</span>
<span class="w"> </span><span class="nt">updateStrategy</span><span class="p">:</span>
<span class="w"> </span><span class="nt">rollingUpdate</span><span class="p">:</span>
<span class="w"> </span><span class="nt">maxSurge</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0</span>
<span class="w"> </span><span class="nt">maxUnavailable</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10%</span>
<span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">RollingUpdate</span>
<span class="nt">status</span><span class="p">:</span>
<span class="w"> </span><span class="nt">currentNumberScheduled</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">desiredNumberScheduled</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">numberAvailable</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">numberMisscheduled</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0</span>
<span class="w"> </span><span class="nt">numberReady</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">observedGeneration</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
</pre></div>
<p>eks-pod-identity-agent 组件具有如下特点:</p>
<ul class="simple">
<li>依赖节点 IAM 角色被授予如下 IAM 权限策略。</li>
</ul>
<div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"eks-auth:AssumeRoleForPodIdentity"</span><span class="p">,</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>
<ul class="simple">
<li>组件 Pod 使用 <tt class="docutils literal">hostNetwork</tt> 。</li>
<li>组件内的服务将监听 80 和 2703 端口。</li>
<li>其中 80 端口监听的 IPv4 地址为 <tt class="docutils literal">169.254.170.23</tt>, IPv6 地址为 <tt class="docutils literal"><span class="pre">[fd00:ec2::23]</span></tt> 。</li>
</ul>
<div class="highlight"><pre><span></span>$<span class="w"> </span>ss<span class="w"> </span>-anltp<span class="w"> </span><span class="p">|</span>grep<span class="w"> </span>eks-pod
LISTEN<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">4096</span><span class="w"> </span><span class="m">127</span>.0.0.1:2703<span class="w"> </span><span class="m">0</span>.0.0.0:*<span class="w"> </span>users:<span class="o">((</span><span class="s2">"eks-pod-identit"</span>,pid<span class="o">=</span><span class="m">3798</span>,fd<span class="o">=</span><span class="m">5</span><span class="o">))</span>
LISTEN<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">4096</span><span class="w"> </span><span class="m">169</span>.254.170.23:80<span class="w"> </span><span class="m">0</span>.0.0.0:*<span class="w"> </span>users:<span class="o">((</span><span class="s2">"eks-pod-identit"</span>,pid<span class="o">=</span><span class="m">3798</span>,fd<span class="o">=</span><span class="m">4</span><span class="o">))</span>
LISTEN<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">4096</span><span class="w"> </span><span class="o">[</span>fd00:ec2::23<span class="o">]</span>:80<span class="w"> </span><span class="o">[</span>::<span class="o">]</span>:*<span class="w"> </span>users:<span class="o">((</span><span class="s2">"eks-pod-identit"</span>,pid<span class="o">=</span><span class="m">3798</span>,fd<span class="o">=</span><span class="m">3</span><span class="o">))</span>
</pre></div>
<ul class="simple">
<li>组件将通过 init 容器在节点上创建一个 IPv4 地址为 <tt class="docutils literal">169.254.170.23</tt>, IPv6 地址为 <tt class="docutils literal"><span class="pre">[fd00:ec2::23]</span></tt> 的网络接口 <tt class="docutils literal"><span class="pre">pod-id-link0</span></tt> 。</li>
</ul>
<div class="highlight"><pre><span></span>pod-id-link0:<span class="w"> </span><span class="nv">flags</span><span class="o">=</span><span class="m">195</span><UP,BROADCAST,RUNNING,NOARP><span class="w"> </span>mtu<span class="w"> </span><span class="m">1500</span>
<span class="w"> </span>inet<span class="w"> </span><span class="m">169</span>.254.170.23<span class="w"> </span>netmask<span class="w"> </span><span class="m">255</span>.255.255.255<span class="w"> </span>broadcast<span class="w"> </span><span class="m">0</span>.0.0.0
<span class="w"> </span>inet6<span class="w"> </span>fe80::2078:53ff:fe2f:c723<span class="w"> </span>prefixlen<span class="w"> </span><span class="m">64</span><span class="w"> </span>scopeid<span class="w"> </span>0x20<link>
<span class="w"> </span>inet6<span class="w"> </span>fd00:ec2::23<span class="w"> </span>prefixlen<span class="w"> </span><span class="m">128</span><span class="w"> </span>scopeid<span class="w"> </span>0x0<global>
<span class="w"> </span>ether<span class="w"> </span><span class="m">22</span>:78:53:2f:c7:23<span class="w"> </span>txqueuelen<span class="w"> </span><span class="m">1000</span><span class="w"> </span><span class="o">(</span>Ethernet<span class="o">)</span>
<span class="w"> </span>RX<span class="w"> </span>packets<span class="w"> </span><span class="m">0</span><span class="w"> </span>bytes<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="o">(</span><span class="m">0</span>.0<span class="w"> </span>B<span class="o">)</span>
<span class="w"> </span>RX<span class="w"> </span>errors<span class="w"> </span><span class="m">0</span><span class="w"> </span>dropped<span class="w"> </span><span class="m">0</span><span class="w"> </span>overruns<span class="w"> </span><span class="m">0</span><span class="w"> </span>frame<span class="w"> </span><span class="m">0</span>
<span class="w"> </span>TX<span class="w"> </span>packets<span class="w"> </span><span class="m">10</span><span class="w"> </span>bytes<span class="w"> </span><span class="m">700</span><span class="w"> </span><span class="o">(</span><span class="m">700</span>.0<span class="w"> </span>B<span class="o">)</span>
<span class="w"> </span>TX<span class="w"> </span>errors<span class="w"> </span><span class="m">0</span><span class="w"> </span>dropped<span class="w"> </span><span class="m">0</span><span class="w"> </span>overruns<span class="w"> </span><span class="m">0</span><span class="w"> </span>carrier<span class="w"> </span><span class="m">0</span><span class="w"> </span>collisions<span class="w"> </span><span class="m">0</span>
</pre></div>
<ul class="simple">
<li>init 容器还会设置下面这样的的路由规则,确保在本机处理发往 <tt class="docutils literal">169.254.170.23</tt> 的流量。</li>
</ul>
<div class="highlight"><pre><span></span><span class="m">169</span>.254.170.23<span class="w"> </span>dev<span class="w"> </span>pod-id-link0
</pre></div>
</div>
<div class="section" id="assumeroleforpodidentity">
<h2 id="hidassumeroleforpodidentity">AssumeRoleForPodIdentity<a class="headerlink" href="#hidassumeroleforpodidentity" title="Permalink to this headline">¶</a></h2>
<p>EKS 提供了一个新的 API <a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_auth_AssumeRoleForPodIdentity.html">AssumeRoleForPodIdentity</a> ,
用于使用 service account oidc token 获取扮演 service account 关联 IAM 角色的 sts token。</p>
<p>service account oidc token 中的 payload 的内容示例如下。</p>
<div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"aud"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"pods.eks.amazonaws.com"</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"exp"</span><span class="p">:</span><span class="w"> </span><span class="mi">1701672885</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"iat"</span><span class="p">:</span><span class="w"> </span><span class="mi">1701586485</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"iss"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://oidc.eks.us-west-2.amazonaws.com/id/DA16E524AXXXXXX"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"kubernetes.io"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"namespace"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"pod"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"test-596475c6d5-xgvml"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"uid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"924e66b2-841e-4969-9fa7-a19f3f6f1029"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"serviceaccount"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"uid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"eca98cb1-ca2e-469b-8f9d-2be9f5a3354f"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"nbf"</span><span class="p">:</span><span class="w"> </span><span class="mi">1701586485</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"sub"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system:serviceaccount:default:default"</span>
<span class="p">}</span>
</pre></div>
<p>可以看到这个 oidc token 跟 IRSA 方案中的 oidc token 相比,除了 aud 不一样外(IRSA 中是 <tt class="docutils literal">sts.amazonaws.com</tt> ),
其他内容都是一样的。</p>
<p>因此,据我猜测,AssumeRoleForPodIdentity 的后端逻辑可能类似下面这样:</p>
<ol class="arabic simple">
<li>首先,基于 oidc 协议解析和校验客户端传递过来的 oidc token 的有效性和合法性。</li>
<li>然后,基于用户配置的 service account 与 IAM 角色关联关系,获取需要扮演的角色信息。</li>
<li>最后,调用 sts API 扮演对应角色,获取客户端所需的 sts token。</li>
</ol>
</div>
<div class="section" id="service-account-iam">
<h2 id="hidservice-account-iam">service account 关联 IAM 角色<a class="headerlink" href="#hidservice-account-iam" title="Permalink to this headline">¶</a></h2>
<p>为了简化用户为 service account 关联 IAM 角色的操作,EKS 新增了一组用于管理 service account 与 IAM 角色关联关系的 API。
同时还增加了对应的 EKS 控制台操作页面,并且关联关系都存储在 EKS 侧,并没有去修改角色的信任策略。</p>
<ul class="simple">
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_CreatePodIdentityAssociation.html">CreatePodIdentityAssociation</a> :为 service account 关联角色。</li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_DescribePodIdentityAssociation.html">DescribePodIdentityAssociation</a> : 查看单条角色关联记录的详情。</li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdatePodIdentityAssociation.html">UpdatePodIdentityAssociation</a> :修改 service account 关联的角色信息。</li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_DeletePodIdentityAssociation.html">DeletePodIdentityAssociation</a> :删除一条角色关联记录。</li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/APIReference/API_ListPodIdentityAssociations.html">ListPodIdentityAssociations</a> :获取当前存在的角色关联记录。</li>
</ul>
</div>
<div class="section" id="section-4">
<h2 id="hidsection-4">权限控制<a class="headerlink" href="#hidsection-4" title="Permalink to this headline">¶</a></h2>
<p>在 IRSA 方案中,我们需要在 IAM 角色的信任策略中配置允许的集群 oidc provider 以及 service account 信息。
但是,在 EKS Pod Identity 方案中,我们不再需要修改角色的信任策略,只需要使用前面介绍的方法使用 EKS 控制台或者 EKS API
即可完成控制角色能被哪些集群的哪些 service account 使用,这些关联关系存储在 EKS 侧,不再需要频繁的更新角色的信任策略。</p>
<p>通过这种方式, EKS Pod Identity 解决了 IRSA 中因为角色信任策略的内容大小限制导致一个角色只能被有限的几个
service account 关联使用的问题 (详见 <a class="reference external" href="https://github.com/aws/containers-roadmap/issues/1408">#148</a> ),
在 EKS Pod Identity 方案中,一个角色可以与不限数量的 service account 进行关联。</p>
<div class="section" id="attribute-based-access-control-abac">
<h3 id="hidattribute-based-access-control-abac">attribute-based access control (ABAC)<a class="headerlink" href="#hidattribute-based-access-control-abac" title="Permalink to this headline">¶</a></h3>
<p>EKS Pod Identity 方案还引入了新的基于属性的访问控制能力(attribute-based access control (ABAC)):
通过 EKS Pod Identity 方案获取到的 sts token 默认都携带了集群信息、命名空间以及 service account 等 tag 属性,
用户可以基于 IAM 提供的 <a class="reference external" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_iam-tags.html">tag 鉴权</a> 特性,
在为角色配置权限策略时,实现基于属性的访问控制能力。</p>
<p>通过 EKS Pod Identity 获取的 sts token 默认携带了如下 tag :</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">eks-cluster-arn</span></tt> :当前集群的 ARN。</li>
<li><tt class="docutils literal"><span class="pre">eks-cluster-name</span></tt> :当前集群的名称。</li>
<li><tt class="docutils literal"><span class="pre">kubernetes-namespace</span></tt>: service account 所在的命名空间名称。</li>
<li><tt class="docutils literal"><span class="pre">kubernetes-service-account</span></tt> :service account 的名称。</li>
<li><tt class="docutils literal"><span class="pre">kubernetes-pod-name</span></tt> :使用 service account 的 pod 的名称。</li>
<li><tt class="docutils literal"><span class="pre">kubernetes-pod-uid</span></tt> :使用 service account 的 pod 的 uid。</li>
</ul>
<div class="highlight"><pre><span></span><span class="nt">"tags"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"eks-cluster-arn"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:eks:us-west-2:5XXXXXXXXXXX:cluster/test"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"eks-cluster-name"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"test"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"kubernetes-namespace"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"kubernetes-service-account"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"kubernetes-pod-name"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"test-596475c6d5-xgvml"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"kubernetes-pod-uid"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"924e66b2-841e-4969-9fa7-a19f3f6f1029"</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">]</span>
</pre></div>
<p>我们在定义角色权限策略的时候,可以通过 <tt class="docutils literal"><span class="pre">${aws:PrincipalTag/<tag-key>}</span></tt> 的方式
在权限策略的 <tt class="docutils literal">Condition</tt> 配置中表示凭证属性中包含的特定 tag 的值。</p>
<div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"s3:GetObject"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"s3:GetObjectTagging"</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"Condition"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"StringEquals"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"s3:ExistingObjectTag/eks-cluster-name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${aws:PrincipalTag/eks-cluster-name}"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"StringEqualsIfExists"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"aws:ResourceTag/kubernetes-namespace"</span><span class="p">:</span><span class="w"> </span><span class="s2">"s3-demo"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"aws:Resourcelag/kubernetes-service-account"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${aws:PrincipalTag/kubernetes-service-account}"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>
<p>通过上面这个示例权限策略,我们可以对通过 EKS Pod Identity 特性扮演角色获取的 sts token 的权限做如下限制:</p>
<ul class="simple">
<li>只允许访问存在名为 <tt class="docutils literal"><span class="pre">eks-cluster-name</span></tt> 的 tag 的 s3 object ,并且 tag 的值必须是当前 sts token 关联集群的名称。</li>
<li>如果 s3 object 存在名为 <tt class="docutils literal"><span class="pre">kubernetes-namespace</span></tt> 的 tag,只允许访问这个 tag 的值是 <tt class="docutils literal"><span class="pre">s3-demo</span></tt> 的 object。</li>
<li>如果 s3 object 存在名为 <tt class="docutils literal"><span class="pre">kubernetes-service-account</span></tt> 的 tag,只允许访问这个 tag 的值是当前 sts token 关联的 service account 名称的 object。</li>
</ul>
</div>
</div>
<div class="section" id="irsa">
<h2 id="hidirsa">与 IRSA 的区别<a class="headerlink" href="#hidirsa" title="Permalink to this headline">¶</a></h2>
<p>根据上面介绍的信息,我们可以比较一下 EKS Pod Identity 与 IRSA 特性的区别,它们主要的区别如下:</p>
<table border="1" class="docutils">
<colgroup>
<col width="29%" />
<col width="36%" />
<col width="35%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">比较项</th>
<th class="head">EKS Pod Identity</th>
<th class="head">IRSA</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>节点 IAM 角色增加额外权限</td>
<td>需要增加 <tt class="docutils literal"><span class="pre">eks-auth:AssumeRoleForPodIdentity</span></tt> 权限</td>
<td><strong>不需要</strong></td>
</tr>
<tr><td>创建 IAM oidc provider</td>
<td><strong>不需要</strong></td>
<td>需要为每个集群创建一个 oidc provider</td>
</tr>
<tr><td>service account 关联角色</td>
<td><strong>通过 EKS API/控制台</strong></td>
<td>配置 service account annotation + 修改角色信任策略</td>
</tr>
<tr><td rowspan="2">一个角色可以关联的 service account 数量</td>
<td rowspan="2"><strong>无限制</strong></td>
<td rowspan="2">角色信任策略有 4096 个字符限制,
最多关联 10 个左右 service account 或 集群</td>
</tr>
<tr></tr>
<tr><td>一个 service account 可以关联的角色数量</td>
<td>一个</td>
<td>无限制</td>
</tr>
<tr><td rowspan="2">角色信任策略修改次数</td>
<td rowspan="2"><strong>只需修改一次</strong> 确保信任
<tt class="docutils literal">pods.eks.amazonaws.com</tt>
以及包含所需的 action</td>
<td rowspan="2">需要为每个关联的集群修改至少一次</td>
</tr>
<tr></tr>
<tr><td>基于 service account 相关属性进行访问控制</td>
<td><strong>通过 ABAC 进行支持</strong></td>
<td>不支持</td>
</tr>
<tr><td rowspan="2">集群类型</td>
<td rowspan="2">只支持 EKS 集群,不支持 AWS Outposts、
不支持 EKS Anywhere、AWS Fargate (Fargate)、自建集群</td>
<td rowspan="2"><strong>仅不支持 AWS Outposts</strong></td>
</tr>
<tr></tr>
<tr><td>数据面依赖</td>
<td>kubelet + eks-pod-identity-agent</td>
<td><strong>kublet</strong></td>
</tr>
<tr><td rowspan="5">稳定性风险</td>
<td rowspan="5">依赖集群控制面和数据面的稳定性 + EKS API;
同时还依赖 eks-pod-identity-agent 的稳定性;
应用 pod 如果先于 eks-pod-identity-agent pod
启动/就绪会出现短暂的无法获取到 sts token 的问题
(比如,同样配置了 <tt class="docutils literal">hostNetwork</tt> 的 pod 在
自动伸缩场景可能会遇到这种情况,以及不建议 CNI、CSI
这些常常会先于 agent pod 启动的组件使用);</td>
<td rowspan="5"><strong>依赖集群控制面和数据面的稳定性 + STS API</strong></td>
</tr>
<tr></tr>
<tr></tr>
<tr></tr>
<tr></tr>
</tbody>
</table>
<p>BTW, 虽然 EKS Pod Identity 方案的官方教程和文档中都是说的需要依赖 eks-pod-identity-agent 这个组件,
但是从前面的内容中我们也可以看到:我们其实也可以在不安装 eks-pod-identity-agent 组件的情况下,使用该方案。
具体来说就是,我们可以通过在应用程序内直接访问 EKS 提供的 AssumeRoleForPodIdentity API 的方式来解除对该组件的依赖。</p>
</div>
<div class="section" id="section-5">
<h2 id="hidsection-5">参考资料<a class="headerlink" href="#hidsection-5" title="Permalink to this headline">¶</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://aws.amazon.com/blogs/aws/amazon-eks-pod-identity-simplifies-iam-permissions-for-applications-on-amazon-eks-clusters/">Amazon EKS Pod Identity simplifies IAM permissions for applications on Amazon EKS clusters | AWS News Blog</a></li>
<li><a class="reference external" href="https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/">Introducing fine-grained IAM roles for service accounts | AWS Open Source Blog</a></li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html">EKS Pod Identities - Amazon EKS</a></li>
<li><a class="reference external" href="https://github.com/aws/amazon-eks-pod-identity-webhook">aws/amazon-eks-pod-identity-webhook: Amazon EKS Pod Identity Webhook</a></li>
<li><a class="reference external" href="https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html">Define permissions for EKS Pod Identities to assume roles based on tags - Amazon EKS</a></li>
<li><a class="reference external" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_iam-tags.html">Controlling access to and for IAM users and roles using tags - AWS Identity and Access Management</a></li>
<li><a class="reference external" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html">IAM JSON policy elements: Condition - AWS Identity and Access Management</a></li>
<li><a class="reference external" href="https://securitylabs.datadoghq.com/articles/eks-pod-identity-deep-dive/">Deep dive into the new Amazon EKS Pod Identity feature | Datadog Security Labs</a></li>
</ul>
</div>
使用 libbpfgo 重写 BCC libbpf-tools 中各个工具的用户态程序2022-11-26T00:00:00+00:002022-11-26T00:00:00+00:00mozillazgtag:mozillazg.com,2022-11-26:2022/11/ebpf-libbpfgo-tools-port-rewriting-the-control-plane-of-bcc-libbpf-tools-in-golang-with-libbpfgo.html<p>最近新开源了一个 eBPF 相关的项目:
<a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools">mozillazg/libbpfgo-tools</a> 。
这个项目的目标是使用 <a class="reference external" href="https://github.com/aquasecurity/libbpfgo">libbpfgo</a> 重写/移植 <a class="reference external" href="https://github.com/iovisor/bcc/tree/master/libbpf-tools">bcc/libbpf-tools</a> 中各个工具的前端程序(即,用户态程序)。
希望能在如何使用 golang 编写 eBPF 程序, 尤其是如何使用 libbpfgo 这个 eBPF 库方面对大家有些许帮助。</p>
<div class="section" id="section-1">
<h2 id="hidsection-1">目标<a class="headerlink" href="#hidsection-1" title="Permalink to this headline">¶</a></h2>
<p>这个项目的目标和原则如下:</p>
<ul class="simple">
<li>所有的 eBPF C 代码全部重用 BCC 仓库中 libbpf-tools 目录下的代码。
我们不会对 BCC 的代码做任何额外的修改,如果有需要修改的地方会提 PR 给上游 BCC 仓库。</li>
<li>所有的用户态程序都使用 libbpfgo 进行实现。</li>
</ul>
</div>
<div class="section" id="section-2">
<h2 id="hidsection-2">状态<a class="headerlink" href="#hidsection-2" title="Permalink to this headline">¶</a></h2>
<p>当前,我们已经完成了最新 v0.25.0 版本 BCC libbpf-tools 全部 46 个工具中 28 个工具的移植工作,
更多工具的移植持续进行中:</p>
<ul class="simple">
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/bashreadline">bashreadline</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/bindsnoop">bindsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/biolatency">biolatency</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/biopattern">biopattern</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/biosnoop">biosnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/biostacks">biostacks</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/bitesize">bitesize</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/cpudist">cpudist</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/drsnoop">drsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/execsnoop">execsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/filelife">filelife</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/filetop">filetop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/mdflush">mdflush</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/mountsnoop">mountsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/oomkill">oomkill</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/opensnoop">opensnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/readahead">readahead</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/sigsnoop">sigsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/solisten">solisten</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/statsnoop">statsnoop</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/syscount">syscount</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcpconnect">tcpconnect</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcpconnlat">tcpconnlat</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcplife">tcplife</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcprtt">tcprtt</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcpsynbl">tcpsynbl</a></li>
<li><a class="reference external" href="https://github.com/mozillazg/libbpfgo-tools/blob/master/tools/tcptracer">tcptracer</a></li>
</ul>
</div>