시작하기전에..
애플리케이션에서 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
를 사용한다.
프로젝트 생성
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