<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>&#x2F;</tabi:base_url>
        <tabi:separator>
            •
        </tabi:separator>
        <tabi:about_feeds>This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader. Visit About Feeds to learn more and get started. It&#x27;s free.</tabi:about_feeds>
        <tabi:visit_the_site>Visit website</tabi:visit_the_site>
        <tabi:recent_posts>Recent posts</tabi:recent_posts>
        <tabi:last_updated_on>Updated on $DATE</tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>k8s</tabi:current_section>
    </tabi:metadata><link rel="extra-stylesheet" href="/skins/indigo_ingot.css?h=d429472afbb246441b1a" /><title>Andrew Wippler's Sketchpad - k8s</title>
        <subtitle>Ideas, blog, etc. </subtitle>
    <link href="/tags/k8s/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="/tags/k8s/" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator><updated>2023-07-18T11:23:43+00:00</updated><id>/tags/k8s/atom.xml</id><entry xml:lang="en">
        <title>From nginx to traefik (and solving X-Forwarded-For)</title>
        <published>2023-07-18T11:23:43+00:00</published>
        <updated>2023-07-18T11:23:43+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-07-18-from-nginx-to-traefik-and-solving-x-forwarded-for/" type="text/html"/>
        <id>/2023-07-18-from-nginx-to-traefik-and-solving-x-forwarded-for/</id>
        
            <content type="html">&lt;p&gt;I recently switched my home setup from &lt;em&gt;nginx&lt;&#x2F;em&gt; to &lt;em&gt;traefik&lt;&#x2F;em&gt;. I had to get used to the new configuration styles and weird doc style of &lt;em&gt;traefik&lt;&#x2F;em&gt;, but suffice to say, I am happy at the end results.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Traefik&lt;&#x2F;em&gt; ships with SNI, allowing me to snoop the connection and prevent unauthorized access to my file server. (One must have the correct &lt;em&gt;hostname&lt;&#x2F;em&gt; to see my shared photos.) My first action was to replace my edge &lt;em&gt;nginx&lt;&#x2F;em&gt; reverse proxy with &lt;em&gt;traefik&lt;&#x2F;em&gt;. If this was a success, then I would move onto replacing &lt;em&gt;nginx&lt;&#x2F;em&gt; in my k8s cluster. I was surprized that after zero OS tuning changes, &lt;em&gt;traefik&lt;&#x2F;em&gt; was able to serve pages faster for my k8s cluster. I initially thought that &lt;em&gt;traefik&lt;&#x2F;em&gt; would perform marginally slower than &lt;em&gt;nginx&lt;&#x2F;em&gt; due to additional &lt;em&gt;HostSNI&lt;&#x2F;em&gt; checks, but that was totally disproved by the first page load.&lt;&#x2F;p&gt;
&lt;p&gt;After switching to &lt;em&gt;traefik&lt;&#x2F;em&gt; inside my k8s cluster, performance improved even more. However, a new problem emerged: I was getting the IPs of my internal traffic logged instead of the real origin IP. While I would not normally care, malicious bots were attempting to brute force my WordPress installations, and I need to block their IPs.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to get the &lt;em&gt;X-Forwarded-For&lt;&#x2F;em&gt; header populated with the true ip by enabling the Proxy Protocol on my edge &lt;em&gt;traefik&lt;&#x2F;em&gt;, setting externalTrafficPolicy: Local on my &lt;em&gt;traefik&lt;&#x2F;em&gt; k8s service, and finally telling &lt;em&gt;traefik&lt;&#x2F;em&gt; to accept the &lt;em&gt;proxyProtocol&lt;&#x2F;em&gt; information from the edge server.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Edge Router providers.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tcp:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  routers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    to-web:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      service: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      rule: HostSNIRegexp(`www.andrewwippler.com`, `andrewwippler.com`, ...)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      entryPoints:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    to-websecure:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      service: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      rule: HostSNIRegexp(`www.andrewwippler.com`, `andrewwippler.com`, ...)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      entryPoints:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      tls:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        passthrough: true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;services:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    web:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      loadBalancer:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        proxyProtocol:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          version: 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        servers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    websecure:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      loadBalancer:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        proxyProtocol:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          version: 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        servers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# traefik k8s deployment and service
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# missing service account definition and CRDs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: apps&#x2F;v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: Deployment
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  replicas: 3 #&amp;lt;-- one for each of my nodes, for failover
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  strategy: #&amp;lt;-- forces k8s to update pods on configuration change
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    rollingUpdate:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      maxSurge: 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      maxUnavailable: 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    type: RollingUpdate
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  selector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    matchLabels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  template:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      affinity: #&amp;lt;-- one replica per node
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        podAntiAffinity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          requiredDuringSchedulingIgnoredDuringExecution:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          - labelSelector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              matchExpressions:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              - key: app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                operator: In
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                values:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                - traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            topologyKey: &amp;quot;kubernetes.io&#x2F;hostname&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      serviceAccountName: traefik-ingress-controller
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      containers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          image: traefik:v2.10.3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          args:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.address=:80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.address=:443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.http.tls
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.http3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --experimental.http3=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --providers.kubernetesingress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --providers.kubernetescrd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --log.level=DEBUG
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.http.redirections.entrypoint.scheme=https
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.http.redirections.entrypoint.to=websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            # - --accesslog
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entryPoints.web.proxyProtocol.trustedIPs=127.0.0.1&#x2F;32,10.0.0.0&#x2F;8,172.16.0.0&#x2F;12,192.168.0.0&#x2F;16 #&amp;lt;-- local CIDRs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entryPoints.websecure.proxyProtocol.trustedIPs=127.0.0.1&#x2F;32,10.0.0.0&#x2F;8,172.16.0.0&#x2F;12,192.168.0.0&#x2F;16 #&amp;lt;-- local CIDRs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          ports:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - name: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              containerPort: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - name: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              containerPort: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: Service
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  type: NodePort
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  selector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ports:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - protocol: TCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      port: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      name: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      targetPort: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - protocol: TCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      port: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      name: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      targetPort: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  externalTrafficPolicy: Local # &amp;lt;--- changed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Kubernetes: Heapster to Metrics Server</title>
        <published>2018-07-09T13:58:16+00:00</published>
        <updated>2018-07-09T13:58:16+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-07-09-kubernetes-heapster-to-metrics-server/" type="text/html"/>
        <id>/2018-07-09-kubernetes-heapster-to-metrics-server/</id>
        
            <content type="html">&lt;p&gt;I recently updated my kubernetes cluster from &lt;code&gt;1.10.2&lt;&#x2F;code&gt; to &lt;code&gt;1.11.0&lt;&#x2F;code&gt;. I noticed heapster was being deprecated and completely removed by version &lt;code&gt;1.13.0&lt;&#x2F;code&gt;. I thought this would be the perfect time to try out metrics-server. I had to download the git repo to apply the kubernetes yaml to my cluster. Since this is sometimes not as ideal as I would like, (I prefer &lt;code&gt;kubectl apply -f http:&#x2F;&#x2F;&lt;&#x2F;code&gt; when it comes from a trusted source) I am writing the below for easy access in the future:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;auth-delegator.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;auth-reader.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-apiservice.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-server-deployment.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-server-service.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;resource-reader.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: this is for clusters running v1.8.0 or greater.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Jenkins-x on home kubernetes cluster</title>
        <published>2018-06-06T12:15:42+00:00</published>
        <updated>2018-06-06T12:15:42+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-06-06-jenkins-x-on-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-06-06-jenkins-x-on-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jenkins-x.io&quot;&gt;Jenkins-x&lt;&#x2F;a&gt; appears to be the next big thing in CI&#x2F;CD workflows - especially if you develop applications on kubernetes. There were a few tweaks I needed to do to set it up:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I had to manually create Persistent Volumes (no big deal, below are what I have for my NFS share)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-chartmuseum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-chartmuseum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 100Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-chartmuseum&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-docker-registry
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-docker-registry
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-docker-registry&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-mongodb
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-mongodb
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-mongodb&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-nexus
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-nexus
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-nexus&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to modify the install line&lt;code&gt;jx install --ingress-namespace ingress-nginx --domain wplr.rocks --tls-acme true --skip-ingress&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to modify the &lt;code&gt;jenkins-x-mongodb&lt;&#x2F;code&gt; deployment to use image &lt;code&gt;mongo:3.6.5-jessie&lt;&#x2F;code&gt;. Still wonder why people use bitnami images.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;securityContext:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  runAsUser: 1024
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;on the &lt;code&gt;jenkins-x-nexus&lt;&#x2F;code&gt; deployment. The container was trying to change permissions on my nfs mount. Not sure why my Synology NFS does not like permission changes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Even after those changes, &lt;code&gt;jenkins-x-monocular-ui&lt;&#x2F;code&gt; still fails to start -_- ... I have run out of time for now. More debugging to come later (MUCH MUCH later)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Allowing outside access to Home Kubernetes Cluster</title>
        <published>2018-04-03T15:36:25+00:00</published>
        <updated>2018-04-03T15:36:25+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-04-03-allowing-outside-access-to-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-04-03-allowing-outside-access-to-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;After I created a home kubernetes cluster, I immediately wanted to allow external access to pods&#x2F;services&#x2F;ingresses hosted inside the cluster. One must be aware that in bare metal environments, there is no receiver of an api call to create a load balancer. Since there is not a scriptable environment available to kubernetes, kubernetes cannot request external IP addresses or provision resources that one has come to expect in cloud environments such as AWS. This is a huge bummer - especially since dynamically built environments are fun to have.&lt;&#x2F;p&gt;
&lt;p&gt;To route traffic to web services inside of kubernetes, you have to options available: &lt;code&gt;ingress&lt;&#x2F;code&gt; and &lt;code&gt;service&lt;&#x2F;code&gt;. Services can be exposed via &lt;code&gt;NodePort&lt;&#x2F;code&gt;, &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt;, or &lt;code&gt;ClusterIP&lt;&#x2F;code&gt;. In bare metal, &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt; would never work (unless you coded your own API call to configure a load balancer outside of kubernetes). &lt;code&gt;ClusterIP&lt;&#x2F;code&gt; might work if you want to manage a routing table somewhere inside your network, and &lt;code&gt;NodePort&lt;&#x2F;code&gt; will work if you want to manage a port forwarding table on your router. None of these options are fun for home labs on bare metal. An &lt;code&gt;Ingress&lt;&#x2F;code&gt; is like a layer 7 firewall in that it reads the hostname and path of the incoming HTTP request and can route to applicable services. This works great for a dynamic environment where I am going to host multiple http endpoints.&lt;&#x2F;p&gt;
&lt;p&gt;The overall view of this traffic is going to be: &lt;code&gt;Internet&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Router&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;k8s Ingress&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;k8s Service&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Pod(s)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To create an ingress in kubernetes, you have to make it a &lt;code&gt;Service&lt;&#x2F;code&gt;. In cloud environments, the &lt;code&gt;Ingress&lt;&#x2F;code&gt; is created as type &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt; in home labs, we create this as type &lt;code&gt;NodePort&lt;&#x2F;code&gt; and port forward on the router to any node in the kubernetes cluster.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl get svc -n ingress-nginx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;default-http-backend   ClusterIP   10.102.173.184           80&#x2F;TCP                       3d
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ingress-nginx          NodePort    10.110.162.247           80:30746&#x2F;TCP,443:32641&#x2F;TCP   3d
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my home lab, I am port forwarding on my router &lt;code&gt;0.0.0.0:80 -&amp;gt; &amp;lt;any_node&amp;gt;:30746&lt;&#x2F;code&gt; and &lt;code&gt;0.0.0.0:443 -&amp;gt; &amp;lt;any_node&amp;gt;:32641&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since I have a non-traditional home router (a Linux &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;2EeaCDu&quot;&gt;server with two nics&lt;&#x2F;a&gt;), I had to either enter these into &lt;code&gt;iptables&lt;&#x2F;code&gt; or I could improve upon that by setting up a load balancer such as &lt;code&gt;nginx&lt;&#x2F;code&gt;. &lt;code&gt;nginx&lt;&#x2F;code&gt; will allow me to port-forward load balance across all my nodes and have an easy config file to edit. Because I also want to use &lt;code&gt;cert-manager&lt;&#x2F;code&gt; with Let&#x27;s Encrypt free SSLs, I chose to use the TCP stream server of &lt;code&gt;nginx&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another hiccup (so to speak) in home based labs, is that ISPs give DHCP addresses. So when my internet IP changes, I need to update the DNS of all my http endpoints. Rather than doing that, I have all my home urls (&lt;code&gt;*.wplr.rocks&lt;&#x2F;code&gt;) CNAME to a single hostname which I update with a script with the correct IP.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Home Kubernetes cluster</title>
        <published>2018-04-02T15:26:52+00:00</published>
        <updated>2018-04-02T15:26:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-04-02-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-04-02-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;So I admit it - I am completely obsessed with Kubernetes. All of the web app&#x2F;api deployment challenges in the past 20 years have been somewhat solved with the Kubernetes orchestration and scheduling platform. Kubernetes brings fault-tolerance, and Highly available systems if set up correctly (i.e. use a Kubernetes cloud installer). I enjoy having the power to write yaml and apply it to infrastructure and it eventually becomes what I told it to be. No longer do I need to write the scripts to do it - it does it for me :)&lt;&#x2F;p&gt;
&lt;p&gt;In my first kubernetes home cluster, I re-used my home router and my old media center as a single node + master, but I was hit by a 2 year old Kubernetes bug. It appears my old PC was out in the open. Since my 2 year old son likes to press power buttons, he came over and constantly pressed the power button on my Kubernetes master. This caused me to find a small mini computer that I could place in my cabinet out of view. I finally settled on &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;2GsTRL3&quot;&gt;this as my computer of choice&lt;&#x2F;a&gt;. At $150&#x2F;each for 4 cores, 4GB RAM, and 32GB nve, I thought it was a good deal and ample to run a few containers per node with a nfs-backed storage array.&lt;&#x2F;p&gt;
&lt;p&gt;These little machines booted via UEFI pxe (after pressing DEL for bios and selecting the Realtek boot in the save&#x2F;exit page). I used this kickstart file which installed CentOS 7 minimal by passing in the &lt;code&gt;ks&lt;&#x2F;code&gt; argument to a CentOS initramfs:&lt;&#x2F;p&gt;
&lt;p&gt;After the servers installed, I ran this script:&lt;&#x2F;p&gt;
&lt;p&gt;Note: for one of the three machines I received, I had to put &lt;code&gt;modprobe br_netfilter&lt;&#x2F;code&gt; in &lt;code&gt;&#x2F;etc&#x2F;rc.local&lt;&#x2F;code&gt; before &lt;code&gt;&#x2F;etc&#x2F;sysctl.d&#x2F;k8s.conf&lt;&#x2F;code&gt; would apply.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>kubernetes health check</title>
        <published>2017-12-08T15:00:22+00:00</published>
        <updated>2017-12-08T15:00:22+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-12-08-kubernetes-health-check/" type="text/html"/>
        <id>/2017-12-08-kubernetes-health-check/</id>
        
            <content type="html">&lt;p&gt;The day before thanksgiving, I was pondering an issue I was having. I was pinning a package to a specific version in my Docker container and the repository I grabbed it from stopped offering this specific version. This resulted in a container that Jenkins responded as being built correctly, but missing an integral package that allowed my application to function properly. This led me to believe I had to implement &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;puppet.com&#x2F;blog&#x2F;using-lumogon-inspect-your-containers&quot;&gt;Puppet&#x27;s Lumogon&lt;&#x2F;a&gt; in my Jenkins build process. Curious if anyone had something like this already developed, I headed over to github.com which eventually led me to compose this tweet:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Step 1: Have k8s technical problem
Step 2: Review &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;kelseyhightower?ref_src=twsrc%5Etfw&quot;&gt;@kelseyhightower&lt;&#x2F;a&gt;&#x27;s recent git pushes
Step 3: Find: &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;ato&#x2F;blob&#x2F;master&#x2F;deployments&#x2F;helloworld.yaml#L26-L29&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;ato&#x2F;blob&#x2F;master&#x2F;deployments&#x2F;helloworld.yaml#L26-L29&lt;&#x2F;a&gt;Step 4: Realize this is exactly something I needed to implement
Step 5: Implement feature
Step 6: Enjoy thanksgiving without worry
Step 7: Blog post&lt;&#x2F;p&gt;
&lt;p&gt;— Andrew J. Wippler (@AndrewWippler) &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;AndrewWippler&#x2F;status&#x2F;933413365837418498?ref_src=twsrc%5Etfw&quot;&gt;November 22, 2017&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; communicates with &lt;code&gt;kubeproxy&lt;&#x2F;code&gt; to either allow a pod to be in service or out of service. At first I thought the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; was a once-and-done check, but I found out later this is not the case. When a pod gets launched, kubernetes waits until the container is in the ready state. We can define what consists of a ready container by the use of probes. Coupled with a kubernetes strategy, we can also define and ensure our application survives broken container updates.&lt;&#x2F;p&gt;
&lt;p&gt;Since the application I am supporting is already HTTP based, making an HTTP check to an endpoint that reports on connectivity to core services was the most trivial to implement. I created a script to verify connectivity to MariaDB, MongoDB, Memcached, Message Queue, and verified certain paths on the NFS share were present. All of these items are important to my application and most of them require certain configuration values in my containers to operate. Having kubernetes run this script every time there is a new pod verifies I will never an experience an outage due to a missing package again. As I mentioned before, I thought the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; was a once-and-done, however, I found that after implementing it, my metrics indicated the script was running every 10 seconds per every replica... this quickly added up!&lt;&#x2F;p&gt;
&lt;p&gt;After some chatting in the #kubernetes-users slack, I was able to get more understanding of the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; and how it was designed to communicate with kubeproxy so that you could &quot;shut off&quot; a container by taking it out of rotation. This was not the behavior I wanted so it was suggested that I create a state file. This state file is created after the check and, if it is present, it skips all checks. Due to the ephemeral nature of container storage, it can be assumed this file will never exist on a pod where this check has not been performed.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Adding a user to k8s RBAC</title>
        <published>2017-12-01T15:00:36+00:00</published>
        <updated>2017-12-01T15:00:36+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-12-01-adding-a-user-to-k8s-rbac/" type="text/html"/>
        <id>/2017-12-01-adding-a-user-to-k8s-rbac/</id>
        
            <content type="html">&lt;p&gt;In order to add a user to a kubernetes cluster, we will need several things: kubectl, CA.crt and CA.key (found in your head node&#x27;s &lt;code&gt;&#x2F;etc&#x2F;kubernetes&#x2F;pki&lt;&#x2F;code&gt; folder), and openssl.&lt;&#x2F;p&gt;
&lt;p&gt;First, create a private key for the new user. In this example, we will name the file employee.key:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl genrsa -out employee.key 2048
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we will need to create a certificate sign request - employee.csr - using the private key we just created (employee.key in this example). Make sure to specify your username and group in the &lt;code&gt;-subj&lt;&#x2F;code&gt; section (CN is for the username and O for the group).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl req -new -key employee.key -out employee.csr -subj &amp;quot;&#x2F;CN=username&#x2F;O=developer&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Generate the final certificate employee.crt by approving the certificate sign request, employee.csr, you made earlier. In this example, the certificate will be valid for 90 days.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl x509 -req -in employee.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out employee.crt -days 90
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Give &lt;strong&gt;employee.crt&lt;&#x2F;strong&gt;, &lt;strong&gt;employee.key&lt;&#x2F;strong&gt;, and &lt;strong&gt;CA.crt&lt;&#x2F;strong&gt; to the new employee and have the employee follow the below steps.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up the cluster
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-cluster k8s.domain.tld --server https:&#x2F;&#x2F;api.k8s.domain.tld --certificate-authority &#x2F;path&#x2F;to&#x2F;CA.crt --embed-certs=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up the credentials (a.k.a login information)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-credentials &amp;lt;name&amp;gt; --client-certificate=&#x2F;path&#x2F;to&#x2F;cert.crt --client-key=&#x2F;path&#x2F;to&#x2F;cert.key --embed-certs=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# bind login to server
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-context k8s.domain.tld --cluster= k8s.domain.tld --user=&amp;lt;name&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Optional: append `--namespace=&amp;lt;namespace&amp;gt;` to the command to set a default namespace.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: You may move the certificates to a safe location since the commands included &lt;code&gt;--embed-certs=true&lt;&#x2F;code&gt;. This saved the certs in base64 format in the kubernetes config.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes I post to my blog so I remember how to do a particular thing. This is one of those times.&lt;&#x2F;p&gt;
</content>
        </entry>
</feed>
