Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue related to the External-IP and loadBalancer in a manged Kubernetes deployment #3

Open
drvgautam opened this issue May 5, 2023 · 31 comments

Comments

@drvgautam
Copy link

Dear Alexandre,

I was attempting to deploy the ABCDesktop (kubernetes-version-3.0) for testing my setup with a few of my own desktop applications. Everything worked fine when tested locally in my Ubuntu (22.04) machine. I then thought to deploy the setup in a DigitalOcean Kubernetes (DOK) cluster (I currently have a 3 nodes cluster). Because the DOK is a managed Kubernetes, so it was straight forward to use the context and deploy using the install.sh script (https://raw.githubusercontent.com/abcdesktopio/conf/main/kubernetes/install.sh), just for the testing purpose. To access the deployed ABCDesktop from an external IP, I changed the NGINX service type from nodePort to loadBalancer in the abcdesktop.yaml, as below. Saved and applied the chnages using 'kubectl apply -f abcdesktop.yaml'. I can now access the abcdesktop from 'http://<EXTERNAL-IP>', but I am unable to sign-in using login usernames and passwords from the OLDAP test samples. 'Sign-in Anonymously also fails. I get the error message:'undefined'. Any suggestions as to what I may be doing wrong here would be very much appreciated. Following are some of the details.

changes in the nginx service block within the abcdesktop.yaml

kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: abcdesktop
spec:
  type: LoadBalancer
  selector:
    run: nginx-od
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30443
    name: http

some additional information about the status of services and nodes in my deployment.

$kubectl get service -w

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   xx.yyy.w.z   <none>        443/TCP   50d

$kubectl get nodes -o=wide

 NAME                             STATUS   ROLES    AGE   VERSION   INTERNAL-IP      EXTERNAL-IP       OS-IMAGE                         KERNEL-VERSION           CONTAINER-RUNTIME
        mkp-kubernetes-node-pool-q2r66   Ready    <none>   50d   v1.25.4   xx.yyy.www.zzz   lll.mmm.nnn.ppp   Debian GNU/Linux 11 (bullseye)   5.18.0-0.deb11.4-amd64   containerd://1.4.13
        mkp-kubernetes-node-pool-q2r6l   Ready    <none>   50d   v1.25.4   sss.ppp.uuu.vvv   iii.jjj.kkk.lll    Debian GNU/Linux 11 (bullseye)   5.18.0-0.deb11.4-amd64   containerd://1.4.13
        mkp-kubernetes-node-pool-q2r6t   Ready    <none>   50d   v1.25.4   aaa.bbb.ccc.ddd   uuu.vvv.www.kkk    Debian GNU/Linux 11 (bullseye)   5.18.0-0.deb11.4-amd64   containerd://1.4.13

$kubectl get services -n abcdesktop

NAME        TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)           AGE
desktop     ClusterIP      None             <none>            <none>            9h
memcached   ClusterIP      xx.yyy.www.zz    <none>            11211/TCP         9h
mongodb     ClusterIP      aa.bbb.cc.dd     <none>            27017/TCP         9h
nginx       LoadBalancer   ll.jjj.kkk.mmm   <EXTERAL-IP>      80:30443/TCP      9h
openldap    ClusterIP      uu.vvv.www.zzz   <none>            389/TCP,636/TCP   9h
pyos        ClusterIP      ss.ooo.pp.kk    <none>             8000/TCP          9h
speedtest   ClusterIP      ii.jjj.kkk.ll    <none>            80/TCP            9h
@drvgautam
Copy link
Author

Just to add a bit more information, I tried to look into the log of my openldap pod in the real time. Following is the log, which seems okay and the user 'Phillip J. Fry' succeeded in signing in successfully. However, in reality, I ended up getting the same error 'undefined' in my abcdesktop browser window.

$kubectl logs -n abcdesktop openldap-od-747846c8dd-4rl72 -c openldap -f

6454d2b3 conn=1005 fd=18 ACCEPT from IP=10.244.0.10:42217 (IP=0.0.0.0:10389)
6454d2b3 conn=1005 op=0 BIND dn="cn=Philip J. Fry,ou=people,dc=planetexpress,dc=com" method=128
6454d2b3 conn=1005 op=0 BIND dn="cn=Philip J. Fry,ou=people,dc=planetexpress,dc=com" mech=SIMPLE ssf=0
6454d2b3 conn=1005 op=0 RESULT tag=97 err=0 text=
6454d2b3 conn=1005 op=1 SRCH base="" scope=0 deref=3 filter="(objectClass=*)"
6454d2b3 conn=1005 op=1 SRCH attr=subschemaSubentry +
6454d2b3 conn=1005 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
6454d2b3 conn=1005 op=2 SRCH base="cn=Subschema" scope=0 deref=3 filter="(objectClass=subschema)"
6454d2b3 conn=1005 op=2 SRCH attr=objectClasses attributeTypes ldapSyntaxes matchingRules matchingRuleUse dITContentRules dITStructureRules nameForms createTimestamp modifyTimestamp * +
6454d2b3 conn=1005 op=2 SEARCH RESULT tag=101 err=0 nentries=1 text=
6454d2b3 conn=1005 op=3 SRCH base="ou=people,dc=planetexpress,dc=com" scope=2 deref=3 filter="(&(objectClass=inetOrgPerson)(cn=philip j. fry))"
6454d2b3 conn=1005 op=3 SRCH attr=cn distinguishedName
6454d2b3 conn=1005 op=3 SEARCH RESULT tag=101 err=0 nentries=1 text=
6454d2b3 conn=1005 op=4 SRCH base="ou=people,dc=planetexpress,dc=com" scope=2 deref=3 filter="(&(objectClass=inetOrgPerson)(cn=philip j. fry))"
6454d2b3 conn=1005 op=4 SRCH attr=cn sn description employeeType givenName jpegPhoto mail ou title uid distinguishedName displayName name
6454d2b3 conn=1005 op=4 SEARCH RESULT tag=101 err=0 nentries=1 text=
6454d2b3 conn=1005 op=5 SRCH base="ou=people,dc=planetexpress,dc=com" scope=2 deref=3 filter="(&(objectClass=inetOrgPerson)(cn=philip j. fry))"
6454d2b3 conn=1005 op=5 SRCH attr=memberOf
6454d2b3 conn=1005 op=5 SEARCH RESULT tag=101 err=0 nentries=1 text=
6454d2b3 conn=1005 op=6 UNBIND
6454d2b3 conn=1005 fd=18 closed

@alexandredevely
Copy link
Member

Hello,

Thank you for using abcdesktop.io, i don't use the DigitalOcean Kubernetes cluster. It's the first time.
Your NGINX service change from nodePort to loadBalancer, it is correct and it should works.

Did you update the od.config file option ?

# set the external URL service if you use a reverse proxy
# default_host_url : 'https://external.domain.org'
default_host_url : 'http://localhost'

You may have top replace http://localhost this your loadBalancer ip address or your FQDN ( if you set one) .

Your ldap log is clear, thank you, you have to go in deep : can you read the pyos log file ?

Get the pod name of pyos

kubectl get pods -l name=daemonset-pyospods -n abcdesktop

You should read

NAME                   READY   STATUS    RESTARTS   AGE
daemonset-pyos-64x6n   1/1     Running   0          63m
daemonset-pyos-llz8r   1/1     Running   0          63m

Then read the log of a (or all) pyos pods

kubectl logs daemonset-pyos-64x6n -n abcdesktop

The pod create process should hang with an error.

Can you also check if your user pod is created ?

kubectl get pods -n abcdesktop

I use the Philip J. Fry login

NAME                            READY   STATUS    RESTARTS       AGE
daemonset-pyos-64x6n            1/1     Running   0              72m
daemonset-pyos-llz8r            1/1     Running   0              72m
fry-262f2                       4/4     Running   0              15s
kubectl describe pods -l access_userid=fry -n abcdesktop

Thank you for your feedback
Alexandre

@alexandredevely
Copy link
Member

Hello Vinay,

I have installed a kubernetes cluster on digitalocean.com too.

Before using a type: LoadBalancer, I would like to confirme with you that a simple port-forward works.

% kubectl get pods -n abcdesktop
NAME                            READY   STATUS    RESTARTS   AGE
daemonset-nginx-4bvhv           1/1     Running   0          26m
daemonset-nginx-mz2pf           1/1     Running   0          26m
daemonset-nginx-v9762           1/1     Running   0          26m
daemonset-pyos-9ttbb            1/1     Running   0          26m
daemonset-pyos-lcmgt            1/1     Running   0          26m
daemonset-pyos-mph5p            1/1     Running   0          26m
memcached-od-5b58d595fb-dk6d7   1/1     Running   0          26m
mongodb-od-6496b46dbd-lrx9j     1/1     Running   0          26m
openldap-od-67db7ddd8d-j2h64    1/1     Running   0          26m
speedtest-od-6d9c7675f-xfwgg    1/1     Running   0          26m

Choose one of nginx front, and run the port forward command line

For example

% kubectl port-forward daemonset-nginx-v9762 --address 0.0.0.0  80:80 -n abcdesktop
Forwarding from 0.0.0.0:80 -> 80

Then open your web browser, you should get the home page, login using LDAP auth or Anonymous auth should works.

Screenshot 2023-05-06 at 12 32 45

Then login, and you get a pod user.

For the first time, you may get a time out error, if all container image can not be downloaded in less than 180 seconds on the worker node.

Screenshot 2023-05-06 at 12 33 55

% kubectl get pods -n abcdesktop                                                   
NAME                            READY   STATUS    RESTARTS   AGE
daemonset-nginx-4bvhv           1/1     Running   0          40m
daemonset-nginx-mz2pf           1/1     Running   0          40m
daemonset-nginx-v9762           1/1     Running   0          40m
daemonset-pyos-9ttbb            1/1     Running   0          40m
daemonset-pyos-lcmgt            1/1     Running   0          40m
daemonset-pyos-mph5p            1/1     Running   0          40m
fry-2cf3a                       4/4     Running   0          4m15s
memcached-od-5b58d595fb-dk6d7   1/1     Running   0          40m
mongodb-od-6496b46dbd-lrx9j     1/1     Running   0          40m
openldap-od-67db7ddd8d-j2h64    1/1     Running   0          40m
speedtest-od-6d9c7675f-xfwgg    1/1     Running   0          40m

The user fry gets the abcdesktop pod fry-2cf3a

See you,

Alexandre

@alexandredevely
Copy link
Member

Hello Vinay,

To use a LoadBalancer in digitalocean.

Could you please update the nginx service section in abcdesktop.yaml file

---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: abcdesktop
spec:
  type: LoadBalancer
  selector:
    run: nginx-od 
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    name: http
---

After the a kubectl apply -f abcdesktop.yaml command , wait for the pending state

% kubectl get services -n abcdesktop
NAME        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
desktop     ClusterIP      None             <none>        <none>            57m
memcached   ClusterIP      10.245.247.50    <none>        11211/TCP         57m
mongodb     ClusterIP      10.245.198.243   <none>        27017/TCP         57m
nginx       LoadBalancer   10.245.172.53    <pending>     80:30443/TCP      57m
openldap    ClusterIP      10.245.109.131   <none>        389/TCP,636/TCP   57m
pyos        ClusterIP      10.245.94.15     <none>        8000/TCP          57m
speedtest   ClusterIP      10.245.67.168    <none>        80/TCP            57m

You get the ip address for your LoadBalancer

% kubectl get services -n abcdesktop
NAME        TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)           AGE
desktop     ClusterIP      None             <none>         <none>            61m
memcached   ClusterIP      10.245.247.50    <none>         11211/TCP         61m
mongodb     ClusterIP      10.245.198.243   <none>         27017/TCP         61m
nginx       LoadBalancer   10.245.172.53    161.35.246.4   80:30443/TCP      61m
openldap    ClusterIP      10.245.109.131   <none>         389/TCP,636/TCP   61m
pyos        ClusterIP      10.245.94.15     <none>         8000/TCP          61m
speedtest   ClusterIP      10.245.67.168    <none>         80/TCP            61m

Then open your web browser to reach the abcdesktop service.
In case, the loadbalancing service give me the ip address 161.35.246.4

Screenshot 2023-05-06 at 13 08 03

Login using Philip J. Fry

Screenshot 2023-05-06 at 13 08 22

And you should get the fry desktop

Screenshot 2023-05-06 at 13 08 56

See you,

Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thank you very much for the help in figuring out the issue. I confirm that the DigitalOcean deployment of the abcdesktop works now perfectly fine as you illustrated in the above when I used the version-3.0(https://github.com/abcdesktopio/conf/blob/main/kubernetes/abcdesktop-3.0.yaml). I was somehow using an older version from (https://raw.githubusercontent.com/abcdesktopio/conf/main/kubernetes/abcdesktop.yaml). From the older version, I had two of the pods (as shown below in the Status column) failing to start. I have no moved on to the version-3, so I do not have those old logs from the pyos and mongodb pods to share here, but I can surely go back and try to reproduce those if you need me to report for debugging purpose. Otherwise, I am happy with the successful deployment using the version 3.0! To import applications in the loadBalancer mode, I use the loadBalancer without the nodePort (curl -X PUT -H 'Content-Type: text/javascript' http://<EXTERNAL-IP>/API/manager/image -d @abcsample.json ) and then everything works fine.

kubectl get pods -n abcdesktop

NAME                            READY   STATUS             RESTARTS          AGE
daemonset-nginx-l6gxq           1/1     Running            0                 13h
daemonset-nginx-sqgrs           1/1     Running            0                 13h
daemonset-nginx-xmn86           1/1     Running            0                 13h
daemonset-pyos-mvmxj            0/1     CrashLoopBackOff   161 (44s ago)     13h
daemonset-pyos-vbhzz            0/1     CrashLoopBackOff   0                 22h
daemonset-pyos-vv7qq            0/1     CrashLoopBackOff   0                 22h
memcached-od-bdcbbcb74-7rkl4    1/1     Running            0                 22h
mongodb-od-5f57999d58-544z7     0/1     CrashLoopBackOff   157 (4m26s ago)   13h
openldap-od-747846c8dd-4rl72    1/1     Running            0                 13h
speedtest-od-6b5f8584f5-qvzfm   1/1     Running            0                 13h

The next I am setting up a MinIO storage facility and aiming to map the ABCDesktop user's home directory to enable a dedicated (persistent?) data storage to make things meaningful with respect to my application that needs a data persistence and exchange. While looking into the abcdesktop installation information, I found some information regarding the persistentVolume . Does the 'pyos' version 3 support such thing? Your insightful suggestion on this side would be very much appreciated.

thanks a lot.
regards,
Vinay

@alexandredevely
Copy link
Member

Hello Vinay,

Thank you for your message, and for this feedback.
You have updated the application pull url path, to use the new loadbalancer address, this is great thank you.

'pyos' version 3 only supports HostPath ( for a kubernetes limitation, subpath is not supported in ephemeral container, and ephemeral container need to know the user home directory path )
Note, you have data persistence with host path, the default design is based on NFS mount point.

But i like your design with Minio to store user volume.
So i will try to add a persistentVolumeClaim for each user, and them bypass the subpath usage for ephemeral container.
If it works and does not take so log time to create a persistentVolumeClaim mapped to a persistentVolume after the login process, we should support Minio and all S3, NFS storage backend ...

Thank you again for your comments and for this new design request with S3/Minio

Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thanks again for considering to look into the minIO integration to enable persistentVolumeClaim. If it works, it will be very helpful feature. I will wait for this feature.
I am facing one more issue related to enabling external OAuth provider in my ABCDesktop kubernetes deployment. Based on the documentation, I added my external authentication providers n the authmanager dictionary within the od.config. I delested, created and restarted the configmap, but I did not get the sign-in buttons of my added authenticators activated. I was hoping to get the buttons, similar to for example what demo.abcdesktop.io shows. Am I missing something here to get the external auth providers activated ?
Screenshot from 2023-05-10 11-05-56

After I make the changes in the od.conf, I delete and restart the configmap using the following three commands,
$kubectl delete configmap abcdesktop-config -n abcdesktop
$kubectl create configmap abcdesktop-config --from-file=od.config -n abcdesktop
$kubectl rollout restart daemonset daemonset-pyos -n abcdesktop

my authmanager dictionary in the od.config looks like as below

#I have set the ldpconf-enabled = False and the external providers enabled
authmanagers: {
  'external': {
    'providers': {
       'materials-marketplace': { 
        'displayname': 'abcdesktop-materials-marketplace', 
        'enabled': True,
        'client_id':     '<MYCLIENT_ID>', 
        'client_secret': '<MYCLIENT_SECRET>', 
        'dialog_url': 'https://github.com/login/oauth/authorize?client_id={client_id}&redirect_uri={callback_url}&scope={scope}&state={state}',
        'auth_url': 'https://github.com/login/oauth/access_token?client_id={client_id}&client_secret={client_secret}&code={code}&redirect_uri={callback_url}&state={state}',
        'userinfo_url': 'https://api.github.com/user/emails',
        'callback_url': 'https://abcdesktop.materials-marketplace.eu/callback',
       },
       'github': {
    	'displayname': 'Github',
    	'enabled': True,
    	'client_id': 'CLIENT_ID_FROM_GITHUB_APP_REG',
    	'client_secret': 'CLIENT_SECRET_FROM_GITHUB_APP_REG',
    	'redirect_uri_prefix': 'http://<EXTERNAL-IP>/hub/oauth_callback',
    	'redirect_uri_querystring': 'http://<EXTERNAL-IP>/hub/oauth_callback?provider=github',
    	'authorization_base_url': 'https://github.com/login/oauth/authorize',
    	'token_url': 'https://github.com/login/oauth/access_token',
    	'userinfo_url': 'https://api.github.com/user',
    	'userinfo_method': 'GET',
    	'userinfomap': {
        	'username': 'login',
        	'name': 'name',
        	'email': 'email'
    	},
    	'scope': 'read:user'
    }
      }
     },
  'metaexplicit': {}, 
  'explicit': {
    'show_domains': True,
    'providers'   : { 
	'planet': { 
		'config_ref': 'ldapconfig',  
		'enabled': False } 
	}
  } 
}

# Note serviceaccount is optional
ldapconfig : {
        'planet': {
                'default'       : True,
                'ldap_timeout'  : 15,
                'ldap_protocol' : 'ldap',
                'ldap_basedn'   : 'ou=people,dc=planetexpress,dc=com',
                'servers'       : [ 'openldap.abcdesktop.svc.cluster.local' ],
                'secure'        : False,
                'serviceaccount': { 'login': 'cn=admin,dc=planetexpress,dc=com', 'password': 'GoodNewsEveryone' },
                'policies': {
                        'acls': None,
                        'rules' : {
				'rule-dummy' : {
				 	'conditions' : [ {'boolean':True, 'expected':True } ],
                                        'expected' : True,
                                        'label':'labeltrue'
				},
                                'rule-ship': {
                                        'conditions' : [ { 'memberOf': 'cn=ship_crew,ou=people,dc=planetexpress,dc=com',   'expected' : True  } ],
                                        'expected' : True,
                                        'label':'shipcrew'
                                },
                                'rule-test': {
                                        'conditions' : [ { 'memberOf': 'cn=admin_staff,ou=people,dc=planetexpress,dc=com', 'expected' : True  } ],
                                        'expected' : True,
                                        'label': 'adminstaff'
                                }
                        }
                } } }

@alexandredevely
Copy link
Member

Hello,

Some entries are missing in documentation ( I have to fix it, thank you )

Here is a provider dict with the materials-marketplace connect button.

abcweb.domain.com is an abcdesktop web site
the 'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth'

Screenshot 2023-05-10 at 16 23 13
'providers': {
      'materials-marketplace': { 
        'displayname': 'abcdesktop-materials-marketplace', 
        'enabled': True,
        'client_id': 'xxx', 
        'client_secret': 'xxx',
        'userinfo_auth': True,
        'scope': [ 'https://www.googleapis.com/auth/userinfo.email',  'openid' ],
        'userinfo_url': 'https://www.googleapis.com/oauth2/v1/userinfo',
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=google',
        'authorization_base_url': 'https://accounts.google.com/o/oauth2/v2/auth',
        'token_url': 'https://oauth2.googleapis.com/token',
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      },
      'google': { 
        'displayname': 'Google', 
        'enabled': True,
        'client_id': 'xxx', 
        'client_secret': 'xxx',
        'userinfo_auth': True,
        'scope': [ 'https://www.googleapis.com/auth/userinfo.email', 'openid' ],
        'userinfo_url': 'https://www.googleapis.com/oauth2/v1/userinfo',
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=google',
        'authorization_base_url': 'https://accounts.google.com/o/oauth2/v2/auth',
        'token_url': 'https://oauth2.googleapis.com/token',
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      },
      'orangeconnect': {
        'displayname': 'DIOD Orange Connect',
        'enabled': True,
        'basic_auth': True,
        'scope': [ 'openid', 'profile', 'email' ],
        'userinfo_auth': True,
        'client_id': 'xxx',
        'client_secret': 'xxx',
        'userinfo_url': 'https://auth.tech.orange/oauth2/userinfo',
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=orangeconnect',
        'authorization_base_url': 'https://auth.tech.orange/oauth2/authorize',
        'token_url': 'https://auth.tech.orange/oauth2/token',
	      'explicitproviderapproval': 'AD',
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      },
      'orange': {       
        'displayname': 'Orange', 
        'enabled': True,
        'basic_auth': True,
        'userinfo_auth': True,
        'scope' : [ 'openid', 'form_filling' ],
        'client_id': 'xxx',
        'client_secret': 'xxx',
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=orange',
        'authorization_base_url': 'https://api.orange.com/openidconnect/fr/v1/authorize',
        'token_url': 'https://api.orange.com/openidconnect/fr/v1/token', 
        'userinfo_url': 'https://api.orange.com/formfilling/fr/v1/userinfo',
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      },
      'facebook': { 
        'displayname': 'Facebook', 
        'enabled': True,
        'userinfo_auth': True,
        'client_id': 'xxx', 
        'client_secret': 'xxx', 
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=facebook',
        'authorization_base_url': 'https://www.facebook.com/dialog/oauth',
        'userinfo_url': 'https://graph.facebook.com/v2.6/me?fields=picture.width(400),name',
        'token_url': 'https://graph.facebook.com/v2.3/oauth/access_token',
        'userinfomap': {
            '*': '*',
            'picture': 'picture.data.url'
        },
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      },
      'github': {
        'displayname': 'Github',
        'enabled': True,
        'basic_auth': True,
        'userinfo_auth': True,
        'scope' : [ 'read:user' ], 
        'client_id': 'xxx',
        'client_secret': 'xxx',
        'redirect_uri_prefix' : 'https://abcweb.domain.com/API/auth/oauth',
        'redirect_uri_querystring': 'manager=external&provider=github',
        'authorization_base_url': 'https://github.com/login/oauth/authorize',
        'token_url': 'https://github.com/login/oauth/access_token',
        'userinfo_url': 'https://api.github.com/user',
        'policies': { 'acl'  : { 'permit': [ 'all' ] } }
      } 
    }

Thank you

Regards,
Alexandre

@drvgautam
Copy link
Author

Great, thank you very much.

regards,
Vinay

@alexandredevely
Copy link
Member

Hello Vinay,

Thank you for your message. The last abcdesktopio/oc.pyos:3.0 image has now a persistentVolumeClaim support for pod and for ephemeralcontainer without subPath option.
You can define persistentVolumeClaim using hostPath or using csidriver via storageClass parameter.

Using hostPath

In your od.config file, define the new entries desktop.homedirectorytype desktop.persistentvolumespec desktop.persistentvolumeclaimspec

  • desktop.homedirectorytype: 'persistentVolumeClaim'
  • desktop.persistentvolumespec: create a new volume for the user's homeDir, for persistentVolume hostPath.
  • desktop.persistentvolumeclaimspec: create a new volume claim for the user's homeDir
# set to persistentVolumeClaim
desktop.homedirectorytype: 'persistentVolumeClaim'

desktop.persistentvolumespec: {
            'storageClassName': '',
            'capacity': { 'storage': '1Gi' },
            'accessModes': [ 'ReadWriteMany' ], 
            'hostPath': { 'path': '/mnt/abcdesktop_volumes/{{ provider }}/{{ userid }}' } }

desktop.persistentvolumeclaimspec: {
            'storageClassName': '',
            'resources': { 
              'requests': { 
                'storage': '1Gi'
              } 
            },
            'accessModes': [ 'ReadWriteMany' ] }

desktop.persistentvolumespec support template values. For example '/mnt/abcdesktop_volumes/{{ provider }}/{{ userid }}'.

  • {{ provider }} is the provider's name templated value.
  • {{ userid }} is the user's id templated value.

The user's home directory inside the pod is located on host to /mnt/abcdesktop_volumes/{{ provider }}/{{ userid }}. The directory is created automatically by kubernetes.

The /mnt/abcdesktop_volumes/ content lists the provider name.

$ ls -la /mnt/abcdesktop_volumes/
total 20
drwxr-xr-x   5 root root 4096 mai   12 12:40 .
drwxr-xr-x 106 root root 4096 mai   11 11:34 ..
drwxr-xr-x   3 root root 4096 mai   12 12:40 anonymous
drwxr-xr-x   3 root root 4096 mai   12 12:39 github
drwxr-xr-x   5 root root 4096 mai   12 12:40 google

For provider google, all users are listed.

$ ls -la /mnt/abcdesktop_volumes/google/
total 20
drwxr-xr-x  5 root root 4096 mai   12 12:40 .
drwxr-xr-x  5 root root 4096 mai   12 12:40 ..
drwxr-x--- 16 2048 2048 4096 mai   12 12:39 103464335761332102620
drwxr-x--- 16 2048 2048 4096 mai   12 12:40 112026272437223559761
drwxr-x--- 16 2048 2048 4096 mai   12 12:39 114102844260599245242

For provider google, the user home directory for 103464335761332102620

$ ls -la /mnt/abcdesktop_volumes/google/103464335761332102620/
total 76
drwxr-x--- 16 2048 2048 4096 mai   12 12:39 .
drwxr-xr-x  5 root root 4096 mai   12 12:40 ..
-rw-------  1 2048 2048   71 mai   12 12:39 .Xauthority
-rw-rw-r--  1 2048 2048   12 janv. 27 18:36 .Xresources
drwxr-x---  3 2048 2048 4096 mai   12 12:39 .cache
drwxr-x---  6 2048 2048 4096 mai   12 12:39 .config
drwxrwxr-x  3 2048 2048 4096 janv. 27 18:36 .gconf
-rw-r-----  1 2048 2048    0 mai   12 12:39 .gtk-bookmarks
-rw-rw-r--  1 2048 2048  564 janv. 27 18:36 .gtkrc-2.0
drwxr-x---  3 2048 2048 4096 mai   12 12:39 .local
drwxr-x---  2 2048 2048 4096 mai   12 12:39 .store
drwxr-x---  2 2048 2048 4096 mai   12 12:39 .wallpapers
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Desktop
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Documents
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Downloads
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Music
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Pictures
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Public
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Templates
drwxr-x---  2 2048 2048 4096 mai   12 12:39 Videos

The template values can be one of them :

var description
cn Common Name
uid user id
gid group id
uidNumber user id number
gidNumber group id number
homeDirectory homeDirectory
loginShell loginShell
description description
groups groups
gecos gecos
provider provider
protocol protocol
providertype providertype
name user name
userid user id
locale user's locale
template tag value tag value set by auth rules

Note: hostPath supports file permissions and the pod's init commands chown or chmod can be used.

Using CSI for S3 k8s-csi-s3

I was looking for a csi S3 driver for kubernetes https://kubernetes-csi.github.io/docs/drivers.html but
I can't find an official AWS support for S3 as a CSI.

I've only found two fuse drivers :

Please, let me know if you can find an official driver for S3 as a CSI.

Install a CSI for S3

I use the https://github.com/yandex-cloud/k8s-csi-s3 as a CSI for S3 with minio backend.

Follow https://github.com/yandex-cloud/k8s-csi-s3 setup guide and test with the sample pod to make sure that fuse mount the S3 file system.

Update storageclass.yaml

Add bucket: abcdesktop to use an existing bucket

---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: csi-s3
provisioner: ru.yandex.s3.csi
parameters:
  mounter: geesefs 
  # you can set mount options here, for example limit memory cache size (recommended)
  options: "--memory-limit 1000 --dir-mode 0777 --file-mode 0666"
  # to use an existing bucket, specify it here:
  bucket: abcdesktop
  csi.storage.k8s.io/provisioner-secret-name: csi-s3-secret
  csi.storage.k8s.io/provisioner-secret-namespace: kube-system
  csi.storage.k8s.io/controller-publish-secret-name: csi-s3-secret
  csi.storage.k8s.io/controller-publish-secret-namespace: kube-system
  csi.storage.k8s.io/node-stage-secret-name: csi-s3-secret
  csi.storage.k8s.io/node-stage-secret-namespace: kube-system
  csi.storage.k8s.io/node-publish-secret-name: csi-s3-secret
  csi.storage.k8s.io/node-publish-secret-namespace: kube-system

Update od.config

In your od.config file, define the entry desktop.persistentvolumeclaimspec

  • desktop.homedirectorytype: 'persistentVolumeClaim' to use the persistentVolumeClaim features.
  • desktop.persistentvolumespec: None to skip the persistent volume provisioning.
  • desktop.persistentvolumeclaimspec create a new volume claim for the user's homeDir, the storageClassName csi-s3
# set to persistentVolumeClaim
desktop.homedirectorytype: 'persistentVolumeClaim'
desktop.persistentvolumespec: None
desktop.persistentvolumeclaimspec: {
            'storageClassName': 'csi-s3',
            'resources': { 
              'requests': { 
                'storage': '1Gi'
              } 
            },
            'accessModes': [ 'ReadWriteOnce' ] }

The mounter options

By default the storageclass use mounter: geesefs. geesefs does not store file permissions and the init commands chown or chmod exit with no zero value, then the pod does not start.
All files belongs to root, but with correct permissions options: "--memory-limit 1000 --dir-mode 0777 --file-mode 0666".

Update the 'init' in desktop.pod dict

'init': { 
    'image': 'busybox',
    'enable': True,
    'pullpolicy':  'IfNotPresent',
    'securityContext': {
        'runAsUser':   0,
        'runAsGroup':  0 
    },
    'acl':  { 'permit': [ 'all' ] },
    'command':  [ 'sh', '-c',  'chown {{ uidNumber }}:{{ gidNumber }} ~ || true && chmod 750 ~ || true' ] 
  },

I can't make it works with another mounter like mounter: s3fs, but it should work too and support the file permissions.

kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                             STORAGECLASS               REASON   AGE
pvc-81a65ed9-b98e-462c-86c6-36c89c3d4f1b   1Gi        RWO            Delete           Bound    abcdesktop/github-12896316-96cb5                  csi-s3                              2m46s
kubectl get pvc -n abcdesktop
NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGE
github-12896316-96cb5                  Bound    pvc-81a65ed9-b98e-462c-86c6-36c89c3d4f1b   1Gi        RWO            csi-s3                     2m21s

On the minio console you get the objects

Screenshot 2023-05-12 at 18 09 18

Feel free to give me your feedback. I hope that k8s-csi-s3 is stable enough.

Alexandre

@alexandredevely
Copy link
Member

Hi Vinay,

The is an issue on k8s-csi-s3 yandex-cloud/k8s-csi-s3#45

We need to add --setuid 0 to the options, to fix the umount command.
This StorageClass yaml file works fine on digitalocean cloud service.

---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: csi-s3
provisioner: ru.yandex.s3.csi
parameters:
  mounter: geesefs
  # you can set mount options here, for example limit memory cache size (recommended)
  options: "--memory-limit 1000 --dir-mode 0777 --file-mode 0666 --setuid 0"
  # to use an existing bucket, specify it here:
  bucket: abcdesktop
  csi.storage.k8s.io/provisioner-secret-name: csi-s3-secret
  csi.storage.k8s.io/provisioner-secret-namespace: kube-system
  csi.storage.k8s.io/controller-publish-secret-name: csi-s3-secret
  csi.storage.k8s.io/controller-publish-secret-namespace: kube-system
  csi.storage.k8s.io/node-stage-secret-name: csi-s3-secret
  csi.storage.k8s.io/node-stage-secret-namespace: kube-system
  csi.storage.k8s.io/node-publish-secret-name: csi-s3-secret
  csi.storage.k8s.io/node-publish-secret-namespace: kube-system

@alexandredevely
Copy link
Member

Hi Vinay,

Digitalocean provides a storageClassName: do-block-storage for the kubernetes cluster.
It works fine, with good performance, better than hosting a S3 gateway.

I share the od.config file, the

# set to persistentVolumeClaim
desktop.homedirectorytype: 'persistentVolumeClaim'
desktop.persistentvolumespec: None
desktop.persistentvolumeclaimspec: {
            'storageClassName': 'do-block-storage',
            'resources': {
              'requests': {
                'storage': '1Gi'
              } 
            },
            'accessModes': [ 'ReadWriteOnce' ] }

See you,

Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thank you for adding persistentVolumeClaim feature in the abcdesktopio/oc.pyos:3. This is excellent and works flawlessly. I struggled with hosting a S3 gateway, but the do-block-storage works very nicely. Thank you very much for the help in setting up the abcdesktop on cloud cluster.

In the meantime, I also tried to enable ssl certificates using a rather cumbersome approach, which still has some issues, but I am debugging it. I may seek your advice if I do not succeed. I am using ingress-controller, cert-manager, nginx-ingress resource and in the end I use a networkpolicy to enable communication between the the two loadBalancers (ingress-controller and abcdesktop-nginx) pods to communicate to allow passing the security http01 challenge. This tool chain looks a bit complex and I am not sure if this is the right way to do this.

thanks again.
regards,
Vinay

@alexandredevely
Copy link
Member

Dear Vinay,

I've just run a test with an external domain, get a SSL certificat with Letsencrypt. Digital ocean does it for you. The SSL is established to the digital ocean (HTTPS) LoadBalancer, then incoming request goes into nginx HTTP.
You need to add annotations to the nginx services like :

---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: abcdesktop
  annotations:
    service.beta.kubernetes.io/do-loadbalancer-protocol: "http"
    service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
    service.beta.kubernetes.io/do-loadbalancer-protocol: "https"
    service.beta.kubernetes.io/do-loadbalancer-certificate-id: "xxxxxx-yyyy-zzzzz-aaaaa-bbbbbbbbbbb"
    service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
spec:   
  type: LoadBalancer
  selector:
    run: nginx-od
  ports:  
  - protocol: TCP
    port: 80 
    targetPort: 80
    name: http 
  - protocol: TCP
    port: 443  
    targetPort: 80
    name: https
---

See you
Alexandre

@drvgautam
Copy link
Author

drvgautam commented Jun 12, 2023

Dear Alexandre,
Thanks for this suggestion and sorry for a delayed reply. It worked fine with the SSL certificate setup using this approach. My abcdesktop deployment is working fine now ( webpage: https://promo-abcloudtop.io). However, I have just a few of the applications running that I previously added (before adding SSL certificate and forwarding) using
curl -X PUT -H 'Content-Type: text/javascript' http://LOADBALANCER_IP/API/manager/image -d @APPLICATION_NAME.d.3.0.json.
Now when I try to add new applications using using the domain name in place of the IP
(curl -X PUT -H 'Content-Type: text/javascript' https://promo-abcloudtop.io/API/manager/image -d @APPLICATION_NAME.d.3.0.json),
I get the following error.

{"status": 403, "message": "ip address is denied"}.
It seems I can no more access the 'manager' API end point. I checked my firewalls in the Digital Ocean and it seems okay; my IP address should be allowed to access the endpoint. I was reading this documentation related to the controllers https://www.abcdesktop.io/3.0/config/controllers/, but could not figure out what's wrong.

regards,
Vinay

@alexandredevely
Copy link
Member

alexandredevely commented Jun 16, 2023

Hello Vinay,

Thank you for your message, you've done a great job.

The ManagerController endpoint is protected by default ip filter.
Only ip source in the network [ '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fd00::/8', '169.254.0.0/16' , '127.0.0.0/8' ] can reach the ManagerController endpoint.
Your request come from internet and your ip is denied by default.

To by pass you can

  • use a kubectl port-forward
# I choose a free local tcp port 30400
NGINX_POD_NAME=$(kubectl get pods -l run=nginx-od -o jsonpath={.items..metadata.name} -n abcdesktop)
kubectl port-forward $NGINX_POD_NAME --address 0.0.0.0 30400:80 -n abcdesktop &

Then run the curl command to reach the manager

curl -X GET -H 'Content-Type: text/javascript' http://localhost:30400/API/manager/images

-- OR --

  • update the od.config file in the ManagerController section add the property apikey like 'apikey' : [ 'AyfIgCat239F33et8A5FgAbPd9']

Example

controllers: { 
  'ManagerController': { 
    'apikey' : [ 'AyfIgCat239F33et8A5FgAbPd9'], 
    'permitip': [ '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fd00::/8', '169.254.0.0/16', '127.0.0.0/8' ] },
  'StoreController':   { 'wrapped_key': {} },
  'ComposerController' : { 'requestsallowed' : { 'getdesktopdescription': False } },
  'DesktopController' :  { 'requestsallowed' : { 'dns': False }, 'permitip': [  '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fd00::/8', '169.254.0.0/16', '127.0.0.0/8' ] } } 

Then run the curl command with the X-API-Key header to reach the manager

curl -X GET -H 'X-API-Key: AyfIgCat239F33et8A5FgAbPd9' -H 'Content-Type: text/javascript' http://LOADBALANCER_IP/API/manager/images

See you
Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thank you for this very helpful note. I have been using a temporary workaround to run CURL command to reach the manager API after SSL certificates. I created two manifest YAML versions, one with SSL certificate and the other without. To PUT application containers, I switched between the two versions. It worked for now.

I am facing another issue with the abcdesktop/oc.nginx:3.0 container. As below, the nginx pods suddenly started to Crash.
$ kubectl get pods -n abcdesktop


NAME                            READY   STATUS             RESTARTS      AGE
daemonset-nginx-cgzc9           0/1     CrashLoopBackOff   1 (17s ago)   21s
daemonset-nginx-gvlng           0/1     CrashLoopBackOff   1 (18s ago)   21s
daemonset-nginx-ncvgv           0/1     CrashLoopBackOff   1 (16s ago)   21s
daemonset-pyos-h8ckc            1/1     Running            0             21s
daemonset-pyos-k4rm4            1/1     Running            0             21s
daemonset-pyos-km57d            0/1     Running            0             21s
memcached-od-bdcbbcb74-rjts2    1/1     Running            0             21s
mongodb-od-d46d79476-lvx96      1/1     Running            0             21s

a pod's description looks as below.
$ kubectl describe pod daemonset-nginx-cgzc9 -n abcdesktop

Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  34s                default-scheduler  Successfully assigned abcdesktop/daemonset-nginx-8flsf to marketplace-kubernetes-node-pool-q2r66
  Normal   Pulled     32s                kubelet            Successfully pulled image "abcdesktopio/oc.nginx:3.0" in 830.722958ms
  Normal   Pulled     30s                kubelet            Successfully pulled image "abcdesktopio/oc.nginx:3.0" in 855.925866ms
  Normal   Pulling    11s (x3 over 33s)  kubelet            Pulling image "abcdesktopio/oc.nginx:3.0"
  Normal   Created    10s (x3 over 32s)  kubelet            Created container nginx
  Warning  Failed     10s (x3 over 32s)  kubelet            Error: failed to create containerd task: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/usr/sbin/nginx": stat /usr/sbin/nginx: no such file or directory: unknown
  Normal   Pulled     10s                kubelet            Successfully pulled image "abcdesktopio/oc.nginx:3.0" in 775.031649ms
  Warning  BackOff    3s (x8 over 29s)   kubelet            Back-off restarting failed container

I could not figure out what is happening. I had to delete my 'loadbalancer' from the digitalocean as a last resort, but that did not help. So, in the end, I pulled 'abcdesktopio/oc.nginx:3.0' and checked if there is /usr/sbin/nginx, and indeed there is no such path. I could see that the image with TAG:3.0 was pushed recently. However, container image abcdesktopio/oc.nginx:latest, does have this path. I would appreciate if you can confirm that the abcdesktopio/oc.nginx:3.0 was changed.

regards,
Vinay

@drvgautam
Copy link
Author

Hi

Hi
I tried the following, but without success.
Replacing the /usr/sbin/nginx by /etc/nginx as below in the abcdesktop.yaml, it throws the execution permission error Error: failed to create containerd task: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/etc/nginx": permission denied: unknown. Because the container is not yet created, I could not run kubectl exec -it <demonset-pod-name> -c nginx -- bin/bash and manually change the permission.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  namespace: abcdesktop
  name: daemonset-nginx
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      name: daemonset-nginxpods
  template:
    metadata:
      namespace: abcdesktop
      labels:
        name: daemonset-nginxpods
        run: nginx-od
        type: frontend
        netpol/speedtest: 'true'
        netpol/memcached: 'true'
        netpol/pyos: 'true'
        netpol/ocuser: 'true'
        netpol/dns: 'true'
    spec:
      containers:
      - name: nginx
        imagePullPolicy: Always
        image: abcdesktopio/oc.nginx:3.0
        command:
            - "/etc/nginx"     <------------------------------ here
        volumeMounts:
          - name: jwtsigningkeys
            mountPath: "/config.signing"
            readOnly: true
          - name: jwtpayloadkeys
            mountPath: "/config.payload"
            readOnly: true
          - name: default-config
            mountPath: /etc/nginx/sites-enabled/default
            subPath: default
            readOnly: true
        ports:
          - containerPort: 80
            name: http
          - containerPort: 443
            name: https
        livenessProbe:
          httpGet:
            path: /
            port: 80
          failureThreshold: 1
          periodSeconds: 10
        startupProbe:
          httpGet:
            path: /
            port: 80
          failureThreshold: 5
          periodSeconds: 10
        resources:
          limits:
            cpu: 2
            memory: 512Mi
          requests:
            cpu: 0.25
            memory: 64Mi
        env:
          - name: JWT_DESKTOP_PAYLOAD_PRIVATE_KEY
            value: "/config.payload/abcdesktop_jwt_desktop_payload_private_key.pem"
          - name: JWT_DESKTOP_SIGNING_PUBLIC_KEY
            value: "/config.signing/abcdesktop_jwt_desktop_signing_public_key.pem"
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
      volumes:
          - name: jwtsigningkeys
            secret:
              secretName: abcdesktopjwtdesktopsigning
          - name: jwtpayloadkeys
            secret:
              secretName: abcdesktopjwtdesktoppayload
          - name: default-config
            configMap:
              name: nginx-config
      dnsPolicy: ClusterFirst

regards,
Vinay

@alexandredevely
Copy link
Member

alexandredevely commented Jun 28, 2023

Hello Vinay,

Nice to get some news of your deployment, thank you.
The nginx image has changed.

Why ?

nginx lua module is not supported in ubuntu:22.04, and the package does not exist anymore.
So I have replaced ubuntu:22.04 docker image by openresty/openresty for oc.nginx image.
The Dockerfile for nginx is here https://raw.githubusercontent.com/abcdesktopio/oc.nginx/main/Dockerfile

Changes

Command

You don't need to set the command parameter.
The abcdesktop.yaml have been updated too, and the command line to start oc.nignx is removed. https://raw.githubusercontent.com/abcdesktopio/conf/main/kubernetes/abcdesktop-3.0.yaml

I'm sorry for this update but abcdesktop requires lua script support to read the encrypted (RSA) jwt payload value.

If you remove

        command:
            - "/etc/nginx"     <------------------------------ here

It should work.

The complete nginx updated section

---
apiVersion: apps/v1
kind: Deployment 
metadata:
  namespace: abcdesktop
  name: nginx-od
  labels:
    abcdesktop/role: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx-od
  template:
    metadata:
      namespace: abcdesktop
      labels:
        name: nginx-od
        run: nginx-od
        type: frontend
        netpol/speedtest: 'true'
        netpol/memcached: 'true'
        netpol/pyos: 'true'
        netpol/ocuser: 'true'
        netpol/dns: 'true'
    spec:
      containers:
      - name: nginx
        imagePullPolicy: Always
        image: abcdesktopio/oc.nginx:3.0
        volumeMounts:
          - name: jwtsigningkeys
            mountPath: "/config.signing"
            readOnly: true
          - name: jwtpayloadkeys
            mountPath: "/config.payload"
            readOnly: true
          - name: default-config
            mountPath: /etc/nginx/sites-enabled/default
            subPath: default
            readOnly: true
        ports:
          - containerPort: 80
            name: http
          - containerPort: 443
            name: https
        livenessProbe:
          httpGet:
            path: /
            port: 80
          failureThreshold: 1
          periodSeconds: 10
        startupProbe:
          httpGet:
            path: /
            port: 80
          failureThreshold: 5
          periodSeconds: 10
        resources:
          limits:
            cpu: 2
            memory: 512Mi
          requests:
            cpu: 0.25
            memory: 64Mi
        env:
          - name: JWT_DESKTOP_PAYLOAD_PRIVATE_KEY
            value: "/config.payload/abcdesktop_jwt_desktop_payload_private_key.pem"
          - name: JWT_DESKTOP_SIGNING_PUBLIC_KEY
            value: "/config.signing/abcdesktop_jwt_desktop_signing_public_key.pem"
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
      volumes:
          - name: jwtsigningkeys
            secret:
              secretName: abcdesktopjwtdesktopsigning
          - name: jwtpayloadkeys
            secret:
              secretName: abcdesktopjwtdesktoppayload
          - name: default-config
            configMap:
              name: nginx-config
      dnsPolicy: ClusterFirst
---

Roles

The ClusterRole have been reduced to simple roles ( in the abcdesktop-3.0.yaml ) by default.
ClusterRole are still supported.

DaemonSet

DaemonSet have been replace by Deployment for oc.nginx and oc.pyos

Feel free to send me some feedback if nginx pod does not start

Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thank you for the note of confirmation to these changes. Niginx pods work fine now.

On a different issue:
I wanted to run Octave container (abcdesktopio/octave.d:3.0), but it was throwing some errors. A log from the tasks manager:

Error setting cipher RC4
40E71AC4F17F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (RC4 : 37), Properties ()
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-9107039'

@alexandredevely
Copy link
Member

alexandredevely commented Jun 29, 2023

Hello Vinay,

I confirm this issue.

octave does not start in gui mode and exit with code 0.

12896316:~$ more /tmp/octave.log 
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-'
12896316:~$ more /tmp/lastcmd.log 
Thu Jun 29 08:27:53 AM Europe 2023 start new application /usr/bin/octave
Thu Jun 29 08:27:53 AM Europe 2023 -> APP=/usr/bin/octave
Thu Jun 29 08:27:53 AM Europe 2023 -> ARGS=
Thu Jun 29 08:27:53 AM Europe 2023 -> APPARGS=
Thu Jun 29 08:27:53 AM Europe 2023 -> id=uid=2048 gid=2048 groups=2048
Thu Jun 29 08:27:53 AM Europe 2023 run init overlay scripts
Thu Jun 29 08:27:53 AM Europe 2023 init overlay scripts done
Thu Jun 29 08:27:53 AM Europe 2023 BASENAME_APP=octave
Thu Jun 29 08:27:53 AM Europe 2023 ~/.Xauthority exists
Thu Jun 29 08:27:53 AM Europe 2023 setting pulseaudio cookie
Thu Jun 29 08:27:53 AM Europe 2023 pusleaudio cookie done exitcode=1
Thu Jun 29 08:27:53 AM Europe 2023 end of init
Thu Jun 29 08:27:53 AM Europe 2023 running /usr/bin/octave at Thu Jun 29 08:27:53 AM Europe 2023
Thu Jun 29 08:27:53 AM Europe 2023 end of app exit_code=0

A local command returns the octave prompt

$ octave
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-12896316'
GNU Octave, version 6.4.0
Copyright (C) 2021 The Octave Project Developers.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type 'warranty'.

Octave was configured for "x86_64-pc-linux-gnu".

Additional information about Octave is available at https://www.octave.org.

Please contribute if you find this software useful.
For more information, visit https://www.octave.org/get-involved.html

Read https://www.octave.org/bugs.html to learn how to submit bug reports.
For information about changes from previous versions, type 'news'.

octave:1> 

We need to add the parameter --gui

$ octave --gui

And octave runs, I'm fixing it

Thank you for this issue

Alexandre

@alexandredevely
Copy link
Member

alexandredevely commented Jun 29, 2023

Hello Vinay,

The octave issue is fixed.

Please update

  • pyos deployment
  • octave image

for pyos deployment

Just delete the pyos pod to pull the new image, and fix error in parameters for applications

kubectl delete pods  -l name=pyos-od -n abcdesktop

for octave

The new repo is abcdesktopio/images

I use localhost:30443 as port forward on digital ocean

wget https://raw.githubusercontent.com/abcdesktopio/images/main/artifact/octave.d.main.json
curl -X POST -H 'Content-Type: text/javascript' http://localhost:30443/API/manager/image -d @octave.d.main.json

The first start will pull the octave image, it can take a while

Screenshot 2023-06-29 at 18 38 04

This image is an ubuntu:22.04 with mesa support.

Thank you for your comments

Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,

Thank you very much. This resolved octave issue, and it works fine now.

regards,
Vinay

@alexandredevely
Copy link
Member

Dear Vinay,

Thank you for your message, I really appreciate your feedbacks

See you,
Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,
I have a puzzling issue with my deployed application. When the user signs-in, he gets a different version of the application, based on the K8s cluster node he gets in. For example, in my deployment, I have three nodes: marketplace-kubernetes-node-pool-q2r66, marketplace-kubernetes-node-pool-q2r6l, marketplace-kubernetes-node-pool-q2r6t. When I sign-in I land in one of these nodes. I check this information from the NODE NAME in the Settings:System:User containers.

My example application is the non-standard application, my own python app, ProMo. In the following snapshots, in the case-I and case-II, I get a different container.
Case-1: I am logged-in as the dummy user Hermed Conrad. The cluster node in this case is marketplace-kubernetes-node-pool-q2r66. This application is from the
Screenshot from 2023-07-07 12-44-08

Case-2: I am logged-in from my GitHub account. The cluster node in this case is marketplace-kubernetes-node-pool-q2r6t, which is actually the recent version of the application that I expect to be there.

Screenshot from 2023-07-07 12-46-33

To update my application container, I follow the following procedure.

*Note: I am not using port-forwarding to add application. I have two versions of abcdesktop.yaml files, one with SSL key and port information and the other without the SSL key. So, I simply switch back and forth when adding applications. I checked that there was no application in either of the cluster nodes when I deleted it.

  1. I copy the container key from sha_id using $curl -X GET -H 'Content-Type: text/javascript' http://MY_DO_LOADBALANCER_IP/API/manager/image
  2. Delete the container $curl -X DELETE -H 'Content-Type: text/javascript' http://MY_DO_LOADBALANCER_IP/API/manager/image/MY_APP_SHA_ID_KEY
  3. Add the app to the manager end point $curl -X PUT -H 'Content-Type: text/javascript' http://MY_DO_LOADBALANCER_IP/API/manager/image -d @abcpromo.d.3.0.json

Best regards,
Vinay

@alexandredevely
Copy link
Member

alexandredevely commented Jul 7, 2023

Hi Vinay,

Your latest application has two folders

  • ProMo_Sandbox8
  • Demo_Sandbox

Your screenshots describe that applications image are not the same one on each node.
You want to run always the latest application on each nodes.

I suppose that the application image are not the latest on all nodes

How to fix and make latest image pulled on each nodes ?

Solution 1 : Manually

Please use this one first, it’s easiest.

I suppose you are running containerd

For each nodes ( in your case please choose marketplace-kubernetes-node-pool-q2r66 first )

  • Get an ssh to your node
  • Run the crictl command to find the old image and pull the new one
crictl -r /var/run/containerd/containerd.sock images ls
crictl -r /var/run/containerd/containerd.sock pull http://docker.io/$YOUR_APPLICATION

Solution 2 :

Update od.config file to force the image policy for ephemeral_container or pod_application as imagePullPolicy: ‘Always’

'ephemeral_container': {
    'enable': True,
    'acl':  { 'permit': [ 'all' ] },
    'imagePullPolicy': ‘Always’
    'securityContext': { 
        'supplementalGroups': [ '{{ supplementalGroups }}' ] ,
        'readOnlyRootFilesystem': False, 
        'allowPrivilegeEscalation': True, 
        'runAsUser':                '{{ uidNumber }}',
        'runAsGroup':               '{{ gidNumber }}'
    }
  },

Then apply od.config changes and restart pyos pod

kubectl create -n abcdesktop configmap abcdesktop-config --from-file=od.config -o yaml --dry-run=client | kubectl replace -n abcdesktop -f -
kubectl delete pods -l run=pyos-od -n abcdesktop

Solution 3 :

By default abcdekstop pyos account is based on a role and not on ClusterRoles.
I reduced the default access for security reasons.

  • A role service account can’t get the list of cluster node.
  • A role service account can get the list of node and then pyos can notify all others pyos instance to update

Delete the default pyos rbac roles and update the new one with ClusterRole

kubectl delete -f https://raw.githubusercontent.com/abcdesktopio/conf/main/kubernetes/rbac-role.yaml
kubectl appy -f https://raw.githubusercontent.com/abcdesktopio/conf/main/kubernetes/rbac-cluster.yaml

Add label to your working nodes

kubectl label node $YOUR_NODE abcdesktopworker=true

Read the page on the doc website https://www.abcdesktop.io/3.0/config/desktop/#desktopnodeselector

Change od.config

Add desktop.nodeselector option in od.config

desktop.nodeselector:  { 'abcdesktopworker': 'true' }

Restart pyos pod

kubectl delete pods -l run=pyos-od -n abcdesktop

Then you have to send your json file again, using PUT

curl -X PUT -H 'Content-Type: text/javascript' http://localhost:30443/API/manager/image -d @YOURFILE.json

Best regards,
Alexandre

@drvgautam
Copy link
Author

Dear Alexandre,
I need help to make data from the 'Ontology_Repository' in my promo application persistent. Please see my previous message for the details about this directory in my application. You may recall from the previous messages that I am using DigitalOcean's block-storage and that works fine (data saved in the 'balloon/home' persists).
My promo application generates data in the 'Ontology_Repository' that I need to make persistent as well. Can I mount this directory from the promo container to the balloon/home or somewhere else? Is there any way to accomplish this? I appreciate your suggestion.

Here's the JSON file I use to generate Dockerfile of promo application.

  "tag": "3.0",
  "acl": { "permit": [ "all" ] },
  "cat": "development",
  "icon": "ProMo_logo.svg",
  "keyword": "promo",
  "showinview": "dock",
  "preruncommands": [
    "RUN apt-get update && apt-get install -qq -y rxvt-unicode evince texlive texlive-science texlive-latex-extra dvipng imagemagick python3-pip python3-setuptools graphviz && rm -rf /var/lib/apt/lists/*",
    "COPY promo_app/ promo_app/"
  ],
  "debpackage": "qt5-default libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0",
  "launch": "run.py.run.py",
  "name": "ProMo",
  "path": "/promo_app/ProMo/tasks/run.py",
  "rules": { "homedir": { "default": true } },
  "template": "abcdesktopio/oc.template.ubuntu.gtk.20.04",
  "postruncommands": [
    "RUN chmod 777 /promo_app/ProMo/tasks/run.py",
    "RUN chown -R 4096:4096 /promo_app/Ontology_Repository",
    "RUN chmod 777 /promo_app/Ontology_Repository",
    "RUN python3 -m pip install --upgrade pip",
    "RUN pip install -r promo_app/requirements.txt"
  ]
}``

Best regards,
Vinay

@alexandredevely
Copy link
Member

Hello Vinay,

Your promo application is executed as a container, and '/promo_app/' content comes from the default image.
I understand that your promo application builds datas in the 'Ontology_Repository' and you share the same root path /promo_app for application binary /promo_app/ProMo for user application data /promo_app/Ontology_Repository.
If I'm wrong or have misunderstood, feel free to let me know.

Could you split computed user's data and application (binary, python code) or put computed user's data path in a config file ?

If you can't, because you can't change the applications source code.

There's is a workaround, but keep in mind that split application binary and application's data should be great.

  1. Create $HOME/Ontology_Repository directory
  2. Create a ln -s from /promo_app/Ontology_Repository to $HOME/Ontology_Repository. I suppose that your application write in /promo_app/Ontology_Repository directory. You can repeat the same ln command for each new file or directory that your application computes.
    In the "postruncommands" add the command ln -s /home/balloon/Ontology_Repository /promo_app/Ontology_Repository

To create $HOME/Ontology_Repository directory ( the first point )

  • You can create it manually ( before starting the application, this is bad, but it works )
  • or add a script in the directory /composer/init.d/ of your application

Example firefox application add a script in the directory /composer/init.d

When firefox application starts, it creates the Download directory in the user's home dir.

{
    "acl": { "permit": [ "all" ] },
    "rules": { "homedir": { "default": true } },
    "cat": "office",
    "comment": "NSS_SDB_USE_CACHE=yes",
    "postruncommands": [
        "COPY composer/init.d/init.firefox /composer/init.d/init.firefox",
        "RUN chmod 755 /composer/init.d/init.firefox",
...

    ],
  • composer /init.d/init.firefox /composer/init.d/init.firefox
more composer/init.d/init.firefox
#!/bin/bash
# create Download directory in user homedir
mkdir -p /home/balloon/Downloads

The init file name suffix must be the same as your basename's application binary

BASENAME_APP=$(basename "$APPBIN")
/composer/init.d/init.${BASENAME_APP}

For firefox

ENV APPBIN "/usr/bin/firefox"

The basename command returns

basename /usr/bin/firefox
firefox

In your case, I suppose you get run.py

basename /promo_app/ProMo/tasks/run.py
run.py

So you need to create a script file composer/init.d/init.run.py
and chmod 755 to allow execute

#!/bin/bash
# create Ontology_Repository directory in user homedir
mkdir -p /home/balloon/Ontology_Repository

I hope this can help promo users to keep computed datas.
Let me know if I have misunderstood your issue.

Best regards,
Alexandre

@drvgautam
Copy link
Author

Thank you very much, Alexandre!
I applied the first approach for now, and that works fine. I will try the second option later. This is very useful in general to know how to make containers' data persistent and accessible from the abcdesktop service.

On a slightly unrelated issue, I was thinking if there could be a way around to run a few applications from the terminal. For example, I have gnuplot and octave (currently I have Octave installed as an application in the ABCDesktop) that I was wondering to access from the command line. Let me be a bit more specific what I mean. In my promo application GUI, I have a small (rxrvt) terminal and from there I can for example run python, likewise I wish to run gnuplot and octave. I tried to add gnuplot and octave in as below, but this failed to build the docker. Is this correct way I am doing and is this possible to achieve?

"preruncommands": [
    "RUN apt-get update && apt-get install -qq -y rxvt-unicode evince gnuplot octave texlive texlive-science texlive-latex-extra dvipng imagemagick python3-pip python3-setuptools graphviz && rm -rf /var/lib/apt/lists/*",
    "COPY promo_app/ promo_app/"
  ],

best regards,
Vinay

@alexandredevely
Copy link
Member

alexandredevely commented Sep 7, 2023

Vinay,

Thank's your your reply. Only the user's home dir can keep your data persistent and accessible.

About your comment 'start another application'

Look at your home directory, and check the content of the directory .local/share/applications/bin/.
You will find all your abcdesktop's applications.

It's allow you to start another applications ( so another container ). I mean a container can ask the control plane to start another one.
During the login process, this directory is updated using the list of application available for the current user. The user's mime database is updated too.

For example

I'm running konsole (rxrvt like) application (a simple terminal) and I would like to start the 2048 application.
Just run the command line in konsole

.local/share/applications/bin/2048-qt.2048-qt 

And the 2048 starts

Screenshot 2023-09-07 at 12 18 21

.local/share/applications/bin/2048-qt.2048-qt returns a json content on konsole's stdout.

{
  method: 'ocrun',
  data: {
    image: '2048-qt.2048-qt',
    args: undefined,
    pod_name: 'fry-3fb98',
    pod_namespace: 'abcdesktop'
  }
}

Of course you can build very big image with all in one (gnuplot, rxrvt, python, promo applications), but abcdesktop offers another design, each application is running as a container.
I hope this can help you.

I don't know why gnuplot and octave can't be build. I will check that point.

Thank you for your comments

Alexandre

@drvgautam
Copy link
Author

drvgautam commented Sep 8, 2023

Dear Alexandre,
Thank you for the useful notes.
Just for the information, while building gnuplot and octave, the error comes from the following packages. I tried with these two: abcdesktopio/oc.template.ubuntu.gtk.20.04 and abcdesktopio/oc.template.ubuntu.20.04.
Errors were encountered while processing: pulseaudio pulseaudio-module-bluetooth libcanberra-pulse:amd64 E: Sub-process /usr/bin/dpkg returned an error code (1)

I already have Octave GUI app and for other plotting related tasks I changed from the gnuplot to the the matplotlib and use Jupyterlab.

thanks for the help.
best,
Vinay

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants