Istio client go

시작하기전에..

애플리케이션에서 Istio CR(Custom Resources)을 생성해야 하는데, 공식적으로 제공하는 라이브러리가 없다.

구글에 검색해 본 결과 istio-client-go가 존재한다. 하지만, 필요한 리소그 몇개가 빠져 있어어서 재미삼아 만들어봤다.

주소 : https://github.com/kangwoo/istio-client-go

준비물

처음에는 kubebuilder를 사용하려 했으나, 현재 버전(2.0.0-beta.0)에서는 복수개의 그룹을 지원하지 않는다. (Multiple groups are not supported yet) 그래서 operator-sdk를 사용한다.

  • golang
  • operator-sdk

프로젝트 생성

operator-sdk의 new 명령어를 사용해서 프로젝트 생성한다.

$ operator-sdk new istio-client-go --repo github.com/kangwoo/istio-client-go
$ cd istio-client-go

istio 추가

$ go get istio.io/api

필요한 리소스 추가

$ operator-sdk add api --api-version=authentication.istio.io/v1alpha1 --kind=Policy
$ operator-sdk add api --api-version=networking.istio.io/v1alpha3 --kind=Gateway
$ operator-sdk add api --api-version=rbac.istio.io/v1alpha1 --kind=ServiceRole
$ operator-sdk add api --api-version=rbac.istio.io/v1alpha1 --kind=ServiceRoleBinding

불필요한 파일 삭제 및 코드 수정

  • PolicySpec 타입 위의 // +k8s:openapi-gen=true 제거
  • PolicyStatus 타입 제거 및 Policy 타입에 Status 제거
  • json 변환 및 deepcopy 구현
import (
      "bufio"
      "bytes"
      "log"
    
      "github.com/gogo/protobuf/jsonpb"
      metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
      istiov1alpha1 "istio.io/api/authentication/v1alpha1"
  )
    
  ...
    
        
  func (p *PolicySpec) MarshalJSON() ([]byte, error) {
      buffer := bytes.Buffer{}
      writer := bufio.NewWriter(&buffer)
      marshaler := jsonpb.Marshaler{}
      err := marshaler.Marshal(writer, &p.Policy)
      if err != nil {
          log.Printf("Could not marshal PolicySpec. Error: %v", err)
          return nil, err
      }
    
      writer.Flush()
      return buffer.Bytes(), nil
  }
    
  func (p *PolicySpec) UnmarshalJSON(b []byte) error {
      reader := bytes.NewReader(b)
      unmarshaler := jsonpb.Unmarshaler{}
      err := unmarshaler.Unmarshal(reader, &p.Policy)
      if err != nil {
          log.Printf("Could not unmarshal PolicySpec. Error: %v", err)
          return err
      }
      return nil
  }
    
  // DeepCopyInto is a deepcopy function, copying the receiver, writing into out. in must be non-nil.
  // Based of https://github.com/istio/istio/blob/release-0.8/pilot/pkg/config/kube/crd/types.go#L450
  func (in *PolicySpec) DeepCopyInto(out *PolicySpec) {
      *out = *in
  }

참고 코드

원본 파일

package v1alpha1
    
  import (
      metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  )
    
  // EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
  // NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
    
  // PolicySpec defines the desired state of Policy
  // +k8s:openapi-gen=true
  type PolicySpec struct {
      // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
      // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
      // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
  }
    
  // PolicyStatus defines the observed state of Policy
  // +k8s:openapi-gen=true
  type PolicyStatus struct {
      // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
      // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
      // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
  }
    
  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
  // Policy is the Schema for the policies API
  // +k8s:openapi-gen=true
  // +kubebuilder:subresource:status
  type Policy struct {
      metav1.TypeMeta   `json:",inline"`
      metav1.ObjectMeta `json:"metadata,omitempty"`
    
      Spec   PolicySpec   `json:"spec,omitempty"`
      Status PolicyStatus `json:"status,omitempty"`
  }
    
  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
  // PolicyList contains a list of Policy
  type PolicyList struct {
      metav1.TypeMeta `json:",inline"`
      metav1.ListMeta `json:"metadata,omitempty"`
      Items           []Policy `json:"items"`
  }
    
  func init() {
      SchemeBuilder.Register(&Policy{}, &PolicyList{})
  }

수정 후 파일

package v1alpha1
    
  import (
      "bufio"
      "bytes"
      "log"
    
      "github.com/gogo/protobuf/jsonpb"
      metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
      istiov1alpha1 "istio.io/api/authentication/v1alpha1"
  )
    
  // EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
  // NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
    
  // PolicySpec defines the desired state of Policy
  type PolicySpec struct {
      // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
      // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
      // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
      istiov1alpha1.Policy
  }
    
    
  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
  // Policy is the Schema for the policies API
  // +k8s:openapi-gen=true
  // +kubebuilder:subresource:status
  type Policy struct {
      metav1.TypeMeta   `json:",inline"`
      metav1.ObjectMeta `json:"metadata,omitempty"`
    
      Spec   PolicySpec   `json:"spec,omitempty"`
  }
    
  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
  // PolicyList contains a list of Policy
  type PolicyList struct {
      metav1.TypeMeta `json:",inline"`
      metav1.ListMeta `json:"metadata,omitempty"`
      Items           []Policy `json:"items"`
  }
    
  func init() {
      SchemeBuilder.Register(&Policy{}, &PolicyList{})
  }
    
  func (p *PolicySpec) MarshalJSON() ([]byte, error) {
      buffer := bytes.Buffer{}
      writer := bufio.NewWriter(&buffer)
      marshaler := jsonpb.Marshaler{}
      err := marshaler.Marshal(writer, &p.Policy)
      if err != nil {
          log.Printf("Could not marshal PolicySpec. Error: %v", err)
          return nil, err
      }
    
      writer.Flush()
      return buffer.Bytes(), nil
  }
    
  func (p *PolicySpec) UnmarshalJSON(b []byte) error {
      reader := bytes.NewReader(b)
      unmarshaler := jsonpb.Unmarshaler{}
      err := unmarshaler.Unmarshal(reader, &p.Policy)
      if err != nil {
          log.Printf("Could not unmarshal PolicySpec. Error: %v", err)
          return err
      }
      return nil
  }
    
  // DeepCopyInto is a deepcopy function, copying the receiver, writing into out. in must be non-nil.
  // Based of https://github.com/istio/istio/blob/release-0.8/pilot/pkg/config/kube/crd/types.go#L450
  func (in *PolicySpec) DeepCopyInto(out *PolicySpec) {
      *out = *in
  }

코드 생성

$ operator-sdk generate k8s

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다