Due to the difficulty in using the official java kubernetes client inside a cloud function (basically we didn't know how to put the .kube/config file in the environment for the classes of the client to authenticate against) we have decided to try another route: we are trying to use the Kubernetes API to perform operations against the cluster. We have successfully used this approach to have a Cloud Function create a Cloud Run job using the API
@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception {
GoogleCredentials googleCredentials;
try {
googleCredentials = GoogleCredentials.getApplicationDefault();
} catch (IOException e) {
throw new RuntimeException("Could not load Google Creadentials", e);
}
GKEScopedCredentials gkeScopedCredentials = new GKEScopedCredentials(googleCredentials);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://34.95.xxx.xx/")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
String token = gkeScopedCredentials.getAuthorizationHeader();
GKERestClient gkeRestClient = retrofit.create(GKERestClient.class);
Call < ResponseBody > responseBodyCall = gkeRestClient.createJob(token, RequestBody.create(MediaType.parse("application/json"), "{\n" +
" \"apiVersion\": \"batch/v1\",\n" +
" \"kind\": \"Job\",\n" +
" \"metadata\": {\n" +
" \"name\": \"pi\"\n" +
" },\n" +
" \"spec\": {\n" +
" \"template\": {\n" +
" \"spec\": {\n" +
" \"containers\": [\n" +
" {\n" +
" \"name\": \"pi\",\n" +
" \"image\": \"perl:5.34.0\",\n" +
" \"command\": [\n" +
" \"perl\",\n" +
" \"-Mbignum=bpi\",\n" +
" \"-wle\",\n" +
" \"print bpi(2000)\"\n" +
" ]\n" +
" }\n" +
" ],\n" +
" \"restartPolicy\": \"Never\"\n" +
" }\n" +
" },\n" +
" \"backoffLimit\": 4\n" +
" }\n" +
"}"));
Response < ResponseBody > response = responseBodyCall.execute();
Essentially we are using retrofit to perform the following call:
@POST("/apis/batch/v1/namespaces/cloud-run-example-xxx/jobs")
Call<ResponseBody> createJob(
@Header("Authorization") String authorization,
@Body RequestBody job);
Now this approach worked well for the cloud run API but it isn't working for Kubernetes API, we are getting the following error:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at okhttp3.internal.connection.RealConnection.connectTls ( okhttp3/internal.connection/RealConnection.java:336 )
at okhttp3.internal.connection.RealConnection.establishProtocol ( okhttp3/internal.connection/RealConnection.java:300 )
at okhttp3.internal.connection.RealConnection.connect ( okhttp3/internal.connection/RealConnection.java:185 )
at okhttp3.internal.connection.ExchangeFinder.findConnection ( okhttp3/internal.connection/ExchangeFinder.java:224 )
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection ( okhttp3/internal.connection/ExchangeFinder.java:108 )
at okhttp3.internal.connection.ExchangeFinder.find ( okhttp3/internal.connection/ExchangeFinder.java:88 )
at okhttp3.internal.connection.Transmitter.newExchange ( okhttp3/internal.connection/Transmitter.java:169 )
at okhttp3.internal.connection.ConnectInterceptor.intercept ( okhttp3/internal.connection/ConnectInterceptor.java:41 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:142 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:117 )
at okhttp3.internal.cache.CacheInterceptor.intercept ( okhttp3/internal.cache/CacheInterceptor.java:94 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:142 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:117 )
at okhttp3.internal.http.BridgeInterceptor.intercept ( okhttp3/internal.http/BridgeInterceptor.java:93 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:142 )
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept ( okhttp3/internal.http/RetryAndFollowUpInterceptor.java:88 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:142 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:117 )
at okhttp3.logging.HttpLoggingInterceptor.intercept ( okhttp3/logging/HttpLoggingInterceptor.java:223 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:142 )
at okhttp3.internal.http.RealInterceptorChain.proceed ( okhttp3/internal.http/RealInterceptorChain.java:117 )
at okhttp3.RealCall.getResponseWithInterceptorChain ( okhttp3/RealCall.java:229 )
at okhttp3.RealCall.execute ( okhttp3/RealCall.java:81 )
at retrofit2.OkHttpCall.execute ( retrofit2/OkHttpCall.java:204 )
at functions.Main.service ( functions/Main.java:80 )
Caused by: sun.security.validator.ValidatorException
Via postman the call works well because we can disable the https certificates. Is there any way to add those certificates to the environment of a Cloud Function? or forego them completely?