kylemanna / docker-openvpn

🔒 OpenVPN server in a Docker container complete with an EasyRSA PKI CA
https://hub.docker.com/r/kylemanna/openvpn/
MIT License
8.62k stars 2.37k forks source link

Running the container in Kubernetes #721

Closed hilliao closed 1 year ago

hilliao commented 1 year ago

Hi, @kylemanna , are you still maintaining this repo? I see your last commit was in 2020. I just got the OpenVPN to run on Anthos cluster on bare metal which is a managed Kubernetes product in Google cloud. I'd like to share my steps. I can do so by creating a pull request. But I want to make sure you'd see, review, approve and merge the pull request. Please let me know if you are still working on this repo. Here're the deployment yaml to use. I can share more details once you respond.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: openvpn
  namespace: vpn
  labels:
    app: vpn
spec:
  selector:
    matchLabels:
      app: vpn
  template:
    metadata:
      labels:
        app: vpn
    spec:
      containers:
        - image: kylemanna/openvpn:latest
#          command: [ "/bin/bash", "-c", "--" ]
#          args: [ "while true; do sleep 30; done;" ]
          name: openvpn
          volumeMounts:
            - name: vol-vpn-secret
              mountPath: /etc/openvpn
          securityContext:
            capabilities:
              add:
                - NET_ADMIN
      volumes:
        - name: vol-vpn-secret
          persistentVolumeClaim:
            claimName: pvc-openvpn
SuperJMN commented 1 year ago

Hi @hilliao! I'd like to know if there are additional steps apart from the YAML you posted. Thanks :)

hilliao commented 1 year ago

Not just the deployment is needed. Add volume claim and service yaml files

persistent volume and persistent volume claim for OpenVPN to write to /etc/openvpn in the container

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-vpn
  namespace: vpn
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 1Gi
  local:
    fsType: ext4
    path: /mnt/localpv-share/pvs/vpn
#  nodeAffinity:
#    required:
#      nodeSelectorTerms:
#      - matchExpressions:
#        - key: kubernetes.io/hostname
#          operator: In
#          values:
#          - hp-mina
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-shared
  volumeMode: Filesystem
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-openvpn
  namespace: vpn
  labels:
    type: local
spec:
  storageClassName: local-shared
  volumeMode: Filesystem
  volumeName: local-pv-vpn
  resources:
    requests:
      storage: 1Gi
  accessModes:
    - ReadWriteOnce

Expose the deployment to a service:

apiVersion: v1
kind: Service
metadata:
  name: openvpn
  namespace: vpn
spec:
  selector:
    app: vpn
  ports:
    - port: 1194
      targetPort: 1194
      protocol: UDP
  type: LoadBalancer

Those will be useful for running OpenVPN in Kubernetes in general. I see the last commit was more than 2 years ago. Are you starting to push more commits? Do you plan to create yaml files for those?

SuperJMN commented 1 year ago

Hey @hilliao, I think this repo is abandoned. What if you create a fork and add your Kubernetes YAML files for the community to enjoy them? I'm sure you have a lot to offer.

BTW, the images here don't target some architectures like ARM64. I've found this https://hub.docker.com/r/ixdotai/openvpn is supporting them. Maybe we could use that repo a the base instead.

If you feel more comforable, I could create a fork and give you collaborator access to do the commits you want. Feel free to tell me. The important thing is that your work isn't lost.

Thank you!

hilliao commented 1 year ago

I don't deploy the container in ARM64 but AMD64. Forking the repository would be fine but most of the Google search results about container VPN comes here. I'd rather contact the owner of the repository and add me as a contributor. have you been able to reach the owners of the repository?

SuperJMN commented 1 year ago

No, I haven't tried to contact the owners yet. I assume they haven't had much time to deal with this repo for so long.

To be honest, I don't care about which or what you fork, as long as the community can effectively have a way to deploy Open VPN with Kubernetes without having to make a mess.

I hope you can help people like me. I'm starting to learn Kubernetes, but still not proficient in it.

Thanks anyway 😊

Enviado desde Outlook para Androidhttps://aka.ms/AAb9ysg


From: Hil Liao @.> Sent: Saturday, February 4, 2023 11:44:56 PM To: kylemanna/docker-openvpn @.> Cc: José Manuel Nieto @.>; Comment @.> Subject: Re: [kylemanna/docker-openvpn] Running the container in Kubernetes (Issue #721)

I don't deploy the container in ARM64 but AMD64. Forking the repository would be fine but most of the Google search results about container VPN comes here. I'd rather contact the owner of the repository and add me as a contributor. have you been able to reach the owners of the repository?

— Reply to this email directly, view it on GitHubhttps://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fkylemanna%2Fdocker-openvpn%2Fissues%2F721%23issuecomment-1416867159&data=05%7C01%7C%7Cc08039803d514e006fec08db070170e3%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638111474996725753%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=uvJ9ODLSb4N2%2BmqnENbyZU9Hqd58zYsLdCygpYmrvN0%3D&reserved=0, or unsubscribehttps://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAAXXHW6H4ISBZCKTITBXUILWV3LWRANCNFSM6AAAAAARSPE3AE&data=05%7C01%7C%7Cc08039803d514e006fec08db070170e3%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638111474996725753%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=Od2g6LEpAQ1zrYKd6Zr%2F8ced0l1vi4%2FlVee3%2B47uMGA%3D&reserved=0. You are receiving this because you commented.Message ID: @.***>

hilliao commented 1 year ago

I just emailed the owner. His github profile has an email. Have you tried using my yaml files to deploy the container? How did it work?

SuperJMN commented 1 year ago

I just emailed the owner. His github profile has an email. Have you tried using my yaml files to deploy the container? How did it work?

Wow, I did the same before reading you :)

I've tried to deploy using the information you gave. I have problems with the node affinite for the Persistent Volume. After that, the deployment complained about the mount path:

This is describe over the deployment:

Events:
  Type     Reason       Age                 From               Message
  ----     ------       ----                ----               -------
  Normal   Scheduled    11h                 default-scheduler  Successfully assigned vpn/openvpn-6f664bf569-gtk2d to rpi3
  Warning  FailedMount  11h                 kubelet            Unable to attach or mount volumes: unmounted volumes=[vol-vpn-secret], unattached volumes=[vol-vpn-secret kube-api-access-kvrc7]: timed out waiting for the condition
  Warning  FailedMount  11h                 kubelet            MountVolume.NewMounter initialization failed for volume "local-pv-vpn" : path "/etc/kubernetes/vpn" does not exist
  Warning  FailedMount  41s (x8 over 105s)  kubelet            MountVolume.NewMounter initialization failed for volume "local-pv-vpn" : path "/etc/kubernetes/vpn" does not exist
hilliao commented 1 year ago

I realized that I put the node affinity there to use one of the host's disks. I edited the prior yaml to have nodeAffinity section commented. You may press the page up key to review what's commented and apply the yaml. Without nodeAffinity, the persistent volume may bind to any host's disk. If you still see errors, read more about how to create persistent volume claim to see how you can fix it. The last 2 rows in the describe command is normal as the volume isn't mounted. Let know how it goes!

SuperJMN commented 1 year ago

I realized that I put the node affinity there to use one of the host's disks. I edited the prior yaml to have nodeAffinity section commented. You may press the page up key to review what's commented and apply the yaml. Without nodeAffinity, the persistent volume may bind to any host's disk. If you still see errors, read more about how to create persistent volume claim to see how you can fix it. The last 2 rows in the describe command is normal as the volume isn't mounted. Let know how it goes!

I finally had the PV bound to a local path in node named "rpi3". It's mounted on /home/kubernetes/ovpn.

The pod fails with this message:

Can't find /etc/openvpn/ovpn_env.sh.
Please make sure that OpenVPN is initialized and the proper volume is mounted!

What am I missing?

hilliao commented 1 year ago

You'd have to generate the config script which is the missing ovpn_env.sh. The README.md of the repo states the command to generate that is ovpn_genconfig which is at /usr/local/bin/ovpn_genconfig

Notice the deployment yaml I posted earlier. It has the following commented lines:

#          command: [ "/bin/bash", "-c", "--" ]
#          args: [ "while true; do sleep 30; done;" ]

Apply the deployment file with the 2 lines uncommented to make the container run without entering a crash loop. This is temporary to configure the OpenVPN.

You should identify the exact pod of the deployed container and execute the following command to enter the pod's shell: kubectl -n vpn exec -it pod/openvpn-58c76d8cb-d2gwm -- bash 58c76d8cb-d2gwm is a random string generated by Kubernetes. Yours would be different. After you enter the shell, you'd execute ovpn_genconfig -u udp://VPN.SERVERNAME.COM where VPN.SERVERNAME.COM is the Internet visible DNS name of the Kubernetes cluster. I use my home router to open UDP port 1194 to forward to the Cluster's load balancer IP to achieve it with Google Domains. Once the command succeeds, execute ovpn_initpki to initialize the keys. Those are documented under the Quick Start section in README.md. Skip Start OpenVPN server process; The next step is Generate a client certificate without a passphrase but execute command starting with easyrsa ... directly in the container. Then follow Retrieve the client configuration with embedded certificates ; you want to save the .ovpn file for the VPN clients to use. Once you finish those steps, put back the 2 lines of comment and apply the deployment. The pod should be running fine.

SuperJMN commented 1 year ago

I think I almost have it!

My question is, why do we need to execute this?

          command: [ "/bin/bash", "-c", "--" ]
          args: [ "while true; do sleep 30; done;" ]

Is it a workaround?

hilliao commented 1 year ago

That makes the container run in a sleep loop so it does not crash due to lack of Open VPN proper configuration. That basically overrides the default command to execute and start Open VPN. You will need to comment the 2 lines once OpenVPN has been configured properly. How far are you from success?

SuperJMN commented 1 year ago

That makes the container run in a sleep loop so it does not crash due to lack of Open VPN proper configuration. That basically overrides the default command to execute and start Open VPN. You will need to comment the 2 lines once OpenVPN has been configured properly. How far are you from success?

OK, I'm almost there! I've generated the configuration and now it says this:

getsockopt failed strangely: Operation not permitted
getsockopt failed strangely: Operation not permitted

I don't have a clue of what's happening.

These are the contents of the conf folder

jmn@rpi4:/usr/share/openvpn-data $ find
.
./conf
./conf/vars
./conf/openvpn.conf
./conf/jmn.ovpn
./conf/pki
./conf/pki/.rnd
./conf/pki/reqs
./conf/pki/reqs/superjmn.ddnsfree.com.req
./conf/pki/reqs/jmn.req
./conf/pki/issued
./conf/pki/issued/superjmn.ddnsfree.com.crt
./conf/pki/issued/jmn.crt
./conf/pki/index.txt.attr.old
./conf/pki/private
./conf/pki/private/jmn.key
./conf/pki/private/superjmn.ddnsfree.com.key
./conf/pki/private/ca.key
./conf/pki/dh.pem
./conf/pki/serial
./conf/pki/crl.pem
./conf/pki/certs_by_serial
./conf/pki/certs_by_serial/94831FB96C8E2D91CB347C7C687EC5.pem
./conf/pki/certs_by_serial/A7FABA95680F954DF53BA04E3094F43E.pem
./conf/pki/certs_by_serial/B76CE4ED25158080EF408D62C42750C9.pem
./conf/pki/index.txt.old
./conf/pki/safessl-easyrsa.cnf
./conf/pki/serial.old
./conf/pki/renewed
./conf/pki/renewed/certs_by_serial
./conf/pki/renewed/private_by_serial
./conf/pki/renewed/reqs_by_serial
./conf/pki/openssl-easyrsa.cnf
./conf/pki/index.txt
./conf/pki/ta.key
./conf/pki/ca.crt
./conf/pki/revoked
./conf/pki/revoked/certs_by_serial
./conf/pki/revoked/private_by_serial
./conf/pki/revoked/reqs_by_serial
./conf/pki/index.txt.attr
./conf/ccd
./conf/ovpn_env.sh

This is the deployment YAML I'm using right now:

apiVersion: apps/v1
kind: Deployment
metadata:
  name:  vpn
  namespace: default
  labels:
    app:  vpn
spec:
  selector:
    matchLabels:
      app: vpn
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app:  vpn
    spec:
      containers:
      - name:  vpn
        image:  ixdotai/openvpn
        #command: [ "/bin/bash", "-c", "--" ]
        #args: [ "while true; do sleep 30; done;" ]
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: local
          mountPath: /etc/openvpn
      volumes:
        - name: local
          hostPath:
            path: /usr/share/openvpn-data/conf      

Thanks in advance!

SuperJMN commented 1 year ago

Oops, I missed this section in the Deployment YAML:

          securityContext:
            capabilities:
              add:
                - NET_ADMIN

Now it seems to work!

hilliao commented 1 year ago

Yes, I remember that's required for the container to have permissions to modify the network kernel resources. Are you able to connect from the VPN client?

SuperJMN commented 1 year ago

Yes, I remember that's required for the container to have permissions to modify the network kernel resources. Are you able to connect from the VPN client?

Yes, finally! Thank you a lot :)

hilliao commented 1 year ago

This concludes how to deploy the OpenVPN container in Kubernetes. I just hope the owner of the repo would reply. I don't think he will.